hybris-FlexibleSearch

基础知识

    FlexibleSearch内置采用hybris Commerce Suite的一个强大的检索语言采用hybris商务套件使用基于SQL语法搜索类型和物品

    一个FlexibleSearch语句的执行发生在两个阶段

        pre-parsing(解析)到一个SQL-compliant语句中和运行这个语句在数据库上

        在预解析阶段,FlexibleSearch框架解析FlexibleSearch语法到SQL-compliant里。下面的两个代码段表现出一个FlexibleSearch查询和这个FlexibleSearch语句查询的结果,这是在数据库上执行的语句:

FlexibleSearch查询语句:    

elect {pk}, {code}, {name[de]} from {Product}
在数据库上执行的SQL语句:
SELECT  item_t0.PK , item_t0.Code , lp_t0.p_name
	FROM products item_t0 JOIN productslp lp_t0 ON item_t0.PK = lp_t0.ITEMPK AND lp_t0.LANGPK= 9013632135395968
	WHERE (item_t0.TypePkString IN  ( 23087380955301264 , 23087380955663520 , 23087380955662768 , 23087380955661760 ,
	23087385363574432 , 23087380955568768 , 23087380955206016 ) )

FlexibleSearch采用hybris Commerce Suite的类型系统从实际的数据库表这样你就可以在类型相同级别运行查询。不同于常规的SQL语句,在一个FlexibleSearch查询中您不必指定明确的数据库表名。FlexibleSearch框架解析类型和数据库表自动依赖关系并指定必要UNIONSJOINS在哪里。类型系统和数据库表示之间整个转换过程是自动进行的要访问一个类型FlexibleSearch查询,请用花括号{and}类型代码


SELECT * FROM {Product}

采用hybris Commerce Suite的某一用户帐户的上下文中执行FlexibleSearch查询使用一个会话因为不同的用户帐户访问采用hybris商务套件的不同项目,搜索结果的数量取决于用户的帐户。搜索结果的数目被按类型的访问权限定义这些仅影响采用hybris管理控制台的搜索结果)限制,目录版本和类别

更多的特权用户帐户更多的搜索结果FlexibleSearch产量用户帐户的上下文中默认情况下分配给会话的用户帐户是匿名的所以任何FlexibleSearch查询返回搜索结果相匹配的默认匿名帐户

匿名不同用户帐户的情况下运行FlexibleSearch查询该会话需要被分配给不同的用户帐户,如:

import de.hybris.platform.servicelayer.user.UserService;
...
// Injected by Spring
userService.setCurrentUser(userService.getUserForUID("myUserAccount"));
...

语法概要

FlexibleSearch查询的基本语法如下:


SELECT <selects> FROM <types> ( WHERE <conditions> )? ( ORDER BY <order> )?
一个FlexibleSearch查询包括:


    强制性的<selects>参数对SELECT子句

    强制性的<type>参数为对FROM子句

    强制性的一个可选的<conditions>字段WHERE子句。

    一个可选的ORDER BY子句。

    

SQL Command / Keyword Description / Comment Code Example
ORDER BY {alias:attribute} Display results ordered by the value of attribute. SELECT ... FROM ... ORDER BY...
ASC 排序结果以升序 (a...z, 0...9). SELECT ... FROM ... ORDER BY ... ASC
DESC 排序结果以降序(z...a, 9...0). SELECT ... FROM ... ORDER BY ... DESC
DISTINCT Eliminates double entries in the query result. SELECT DISTINCT ... FROM ...
OR Performs a logical OR compare between two queries. ... WHERE ... OR ...
AND Performs a logical AND compare between two queries. ... WHERE ... AND ...
IS [NOT] NULL Returns the results that are [not] null ... WHERE ... IS [NOT] NULL
[NOT] IN Returns the results that are [not] part of the following statement ... WHERE ... [NOT] IN ...  
[NOT] EXISTS Returns the results that are [not] matching a given subquery. ...WHERE ... EXISTS ( {{ SELECT ... }} )
LIKE Compares to a pattern. ... WHERE ... LIKE '...'
% Wildcard matching any number of characters. ... WHERE ... LIKE '%...'||'...%...'||'...%'
_ Wildcard matching a single character. ... WHERE ... LIKE '...' || '......' ||'..._'
LEFT JOIN ON Merges two tables into one. ... LEFT JOIN ... ON ... = ...
= True if results are equal.  
!=, <> True if results are not equal.  
< True if result 1 is less than result 2.  
<= True if result 1 is equal to or less than result 2.  
> True if result 1 is greater than result 2.  
>= True if result 1 is equal to or greater than result 2.  
CONCAT 连接两个结果 - 在右边侧的例子将返回字符串结果。 CONCAT ( 'resul', 't' )
:o 外连接参数用于包括与在ProductsLP表(=. 表包含本地化产品)以及缺少行匹配结果否则,例如查询将只返回产品 与ProductsLP表中现有行,因为它只会使用JOIN。 SELECT {p:PK}
   FROM {Product AS p}
   WHERE {p:description[en]:o} LIKE '%text%'
   OR {p:description[de]:o} LIKE '%text%'


<selects>


<selects>字段中的指定要返回的数据库列星号*将返回所有数据库SQL约定。要搜索一个属性指定大括号属性标识符SELECT{code}FROM {Product}

要获取本地化的属性使用的语言标识符作为后缀属性名包含在方括号[and]如:

SELECT * FROM {Category}
这个查询返回每个数据库列的Category表。


SELECT {pk},{code},{name[de]} FROM {Product}

产品查询返回数据库pk,code,name[de].



<type>

数值<type>在FROM子句中字段中指定采用hybris Commerce Suite的类型嵌套在大括号{and}这是要搜索例如

SELECT * FROM {Product}
SELECT * FROM {Category JOIN Catalog}


你可以指定一个别名用于区分属性字段使用AS运算符:

SELECT {p.code} FROM {Product AS p} ORDER BY {p.code}


也可以运行JOIN和LEFT JOIN的查询,如

SELECT {cj.code}
    FROM {SyncItemCronJob AS sicj
         JOIN SyncItemJob AS sij
           ON {sicj:job} = {sij:pk}
     }

SELECT {p1.PK},{p2.PK}
    FROM {Product AS p1
         LEFT JOIN Product AS p2
            ON {p1.code} = {p2.code}
     }
WHERE {p1.PK} <> {p2.PK}
    ORDER BY {p1.code} ASC

一定要记住,这是最重要的,整个<type>块必须由封闭{和}不管多种类型.不要试图在多个<type>在FROM子句中尽管这看起来是工作它可能会导致不可预知的错误


子类型


默认情况下指定类型搜索导致FlexibleSearch查询来搜索该类型任何子类型。例如下面的代码片段返回codes和PKs所有实例Product与VariantProduct

SELECT {code},{pk} FROM {Product}

通过增加一个尾部的感叹号FlexibleSearch查询仅搜索指定类型忽略所有subtypes,下面的代码片段搜索Product唯一实例不是VariantProduct


SELECT {code},{pk} FROM {Product!}



当搜索子类型所述FlexibleSearch首先检索字类型进行搜索例如Product的情况下,类型搜索ProductVariantProduct正如商务部的hybris套房类型定义一个项目,因此有一个主键PKFlexibleSearch检索所有类型PK进行搜索。搜索类型PKs的清单放入IN子句WHERE子句


FlexibleSearch Query SQL Statement
SELECT {p:code}, {p:pk} SELECT  item_t0.Code , item_t0.PK
FROM products item_t0
WHERE (item_t0.TypePkString IN  (
   23087380955301264 , 23087380955663520 , 23087380955662768 ,
   23087380955661760 , 23087385363574432 , 23087380955568768 ,
   23087380955206016 )
)
SELECT {p:code}, {p:pk} SELECT  item_t0.Code , item_t0.PK
FROM products item_t0
WHERE (item_t0.TypePkString =  23087380955206016 )



搜索的类型中排除

如果你想确保某些类型FlexibleSearch查询运行省略两种方法在您的处置

    使用请将ItemType操作员和一个参数.这种方法是可行的,如果你可以准备,并通过一个Map,引用要排除作为FlexibleSearch参数类型


final Set<ComposedTypeModel> excludedTypes = new HashSet<ComposedTypeModel>();
excludedTypes.add(getComposedType("mySuborderType"));
 
StringBuilder queryString = new StringBuilder("SELECT {").append(OrderModel.PK).append("} ");
queryString.append("FROM {").append(OrderModel._TYPECODE).append("} ");
queryString.append("WHERE {").append(OrderModel.ITEMTYPE).append("} NOT IN (?excluded)");
 
final FlexibleSearchQuery query = new FlexibleSearchQuery(queryString.toString(), Collections.singletonMap("excluded", excludedTypes));

 

   使用JOIN子句.这种方法是可行的,如果你不能传递参数,例如因为你需要直接输入FlexibleSearch声明


 
  
  
  
  
SELECT {o.PK} FROM {Order AS o JOIN ComposedType AS t ON {o.itemtype}={t.PK} }
WHERE {t.code} NOT IN ('Foo','Bar')


<conditions>

可选的WHERE子句缩小匹配的数量通过指定相匹配的所有搜索结果的至少一个条件<conditions>字段中的值


  避免空间搜索条件条款    一定要避免空间的开始和结束搜索条件来看,随着因为= 'al' 和= 'al '是不相同的搜索条件,导致不同的搜索结果。

SELECT * FROM {Product} WHERE {code} LIKE '%al%'


使用常见的SQL布尔操作符(AND,OR可以连接条件,如

SELECT * FROM {Product} WHERE {code} LIKE '%al%' AND {code} LIKE '%15%'


使用IS NULL操作员发现,没有价值的所有条目

SELECT * FROM {Product} WHERE {code} IS NULL



使用SQL布尔运算符NOT否定的情况是可能的:

SELECT * FROM {Product} WHERE {code} NOT LIKE '%al%'


有可能组合否定和连接条件

SELECT * FROM {Product} WHERE {code} LIKE '%al%' AND {code} NOT LIKE '%15%'



否定IS NULL运算符是不为空

SELECT * FROM {Product} WHERE {code} IS NOT NULL



WHERE子句还允许子选择使用花括号{{and}}如:

SELECT {cat:pk} FROM {Category AS cat} WHERE NOT EXISTS (
   {{ SELECT * FROM {CategoryCategoryRelation} WHERE {target}={cat:pk} }} /* Sub-select */
)


<order>

FlexibleSearch符合SQL语法排序方面通过在ORDER指定属性BY子句搜索结果列表是按照指定类型分类的。此外可以选择指定ASC升序排列搜索结果进行排序(NULL0到9A到Z)或DESC(通过0到A,9 Z,NULL)降序排列搜索结果进行排序。 ASC和DESC是相互排斥的ASC是默认的例如:



下面FlexibleSearch查询按照code数据库列的值按降序排列搜索结果

SELECT {code},{pk} FROM  {Product} ORDER BY {code} DESC



下面FlexibleSearch查询按照代码数据库列搜索结果按升序排列ASC是默认顺序

SELECT {code},{pk} FROM  {Product} ORDER BY {code}



参数

一个FlexibleSearch查询包含可选参数标有前缀问号参数,使您能够传递值FlexibleSearch查询例如,在下面的代码片段,参数Product可用于传递一个搜索模式

SELECT {p:pk} FROM {Product AS p} WHERE {p:code} LIKE ?product





下面FlexibleSearch查询有两个参数的startDate结束日期

SELECT {pk} FROM {Product} WHERE {modifiedtime} >= ?startDate AND {modifiedtime} <=?endDate





使用使用的hybris Commerce Suite的APIFlexibleSearch

使用的hybris商务套件的API FlexibleSearch查询发生在两个步骤这两者都可以在一个Java的语句来完成

    设置查询
    运行查询

构建FlexibleSearch查询

一个FlexibleSearch查询被构造为包含该查询,例如字符串

final String query = "SELECT {pk} FROM {Product}"
// Flexible search service injected by Spring
final SearchResult<ProductModel> searchResult = flexibleSearchService.search(query);





指在FlexibleSearch查询的hybris Commerce Suite的类型属性,如一个项目键(PK,需要构建查询时引用的属性。在情况下,属性是毫不含糊清晰,明确属性就足以静止,建议以引用属性的类型,以及用于消歧采用hybris Commerce Suite的解析,并自动转换属性引用FlexibleSearch查询:
例如:
final String query = "SELECT {" + ProductModel.PK + "} FROM {" + ProductModel._TYPECODE + "}";



String query =
   "SELECT {p:" + ProductModel.PK + "} FROM {" + ProductModel._TYPECODE + " AS p}\n"+
   "WHERE {" + ProductModel.VARIANTTYPE + "} IS NOT NULL"





调用FlexibleSearch

要调用使用API使用flexibleSearchService这始终是可以通过Spring和必须正确注射你的服务如下:一个 FlexibleSearch声明

<bean id="myFancyService" class="de.hybris.platform.foobar.MyFancyService" >
  <property name="flexibleSearchService" ref="flexibleSearchService"/>
</bean>




public class MyFancyService implements FancyService
{
...
  private FlexibleSearchService flexibleSearchService;
 
  @Required
  public void setFlexibleSearchService(final FlexibleSearchService flexibleSearchService)
  {
    this.flexibleSearchService = flexibleSearchService;
  }
...
}





flexibleSearchService.search...)方法返回一个de.hybris.platform.servicelayer.search.SearchResult实例,它持有单个搜索结果列表。访问此列表调用更多搜索getResult()方法

final String query = "SELECT {" + ProductModel.PK + "} FROM {" + ProductModel._TYPECODE + "}";
final SearchResult<ProductModel> searchResult = flexibleSearchService.search(query);
List<ProductModel> result = searchResult.getResult();





然后,您可以处理任何其他Collection情况下,这Collection实例

final String query = "SELECT {" + ProductModel.PK + "} FROM {" + ProductModel._TYPECODE + "}";
final SearchResult<ProductModel> searchResult = flexibleSearchService.search(query);
final ProductModel product = searchResult.getResult().iterator().next();
慎重

通过SearchResult.getResult返回的集合使用翻译方法第一次访问的集合元素该元素被转换为一个项目。
如果该项目已收集搜索结果和特定元素翻译之间取出返回的集合在这个位置空值。



传递参数

传递参数创建一个Map实例持有的参数,并通过Map search...方法,如

final Map<String, Object> params = new HashMap<String, Object>();
 
String query =
"SELECT {" + PriceRowModel.PK + "} FROM {" + PriceRowModel._TYPECODE "} "+
"WHERE {" + PriceRowModel.PRODUCT      + "} = ?product AND "+
      "{" + PriceRowModel.NET          + "} = ?net AND "+
      "{" + PriceRowModel.CURRENCY     + "} = ?currency AND "+
      "{" + PriceRowModel.UNIT         + "} = ?unit AND "+
      "{" + PriceRowModel.UNIT_FACTOR  + "} = ?unitfactor AND "+
      "{" + PriceRowModel.UG           + "} = ?userpricegroup AND "+
      "{" + PriceRowModel.MIN_QUANTITY + "} = ?minquantity AND "+
      "{" + PriceRowModel.PRICE        + "} = ?price ";
 
params.put("product",         product);
params.put("net",         priceCopy.isNet());
params.put("currency",        priceCopy.getCurrency());
params.put("unit",        priceCopy.getUnit());
params.put("unitfactor",  priceCopy.getUnitFactor());
params.put("userpricegroup",  priceCopy.getUserPriceGroup());
params.put("minquantity",     priceCopy.getMinQuantity());
params.put("price",       priceCopy.getPriceValue());
 
final SearchResult<PriceRowModel> searchResult = flexibleSearchService.search(query, params);



搜索结果的实例化

如果你只检索PKS数据库列也就是采用hybris CommerceS SuiteSSS项目只有PKsS并提供一种类型的作为一个Java类可以立即施放PKs表示为实际的模型实例模型换言之,执行以下代码返回CatalogModel实例PKs不是CollectionCollection


final String query = "SELECT {" + CatalogModel.PK + "} FROM {" + CatalogModel._TYPECODE + "} ORDER BY {" + CatalogModel.PK + "} ASC";
final SearchResult<CatalogModel> searchResult = flexibleSearchService.search(query);
如果检索多个数据库您会收到结果几个单独的条目,你将不能够施展搜索结果项实例直接没有就算检索的数据库列之一就是PK



使用的hybris管理控制台FlexibleSearch
    触发的hybris管理控制台FlexibleSearch查询可以有两种方法:使用SavedQuery实例和使用ViewType实例。一个ViewType实例是一个数据库视图的采用hybris Commerce Suite的代表性。一个SavedQuery实例使用FlexibleSearch查询检索采用hybris Commerce Suite的项目,而不是使用GenericSearch的一种手段在HMCViewType表示称为报表定义SavedQuery实例HMC表示它必须指定一个与resultType仅适用与resultType与resultType亚型搜索。适用于所有类型电子商务的hybris套房



Creating a SavedQuery

Go to Managing SavedQuery Items in the hybris Management Console document, section Creating a SavedQuery, for details on how to create aSavedQuery using the hybris Management Console (hMC).

Using a SavedQuery

Go to Managing SavedQuery Items in the hybris Management Console document, section Using a SavedQuery, for details on how to call aSavedQuery using the hMC.

Creating a Report Definition

Go to the Creating Report Definitions Using the hybris Management Console document for details on how to create a Report Definition using the hMC.

Hints

Paging of Search Results

Some FlexibleSearch queries run the risk of returning a very large number of search results, such asSELECT * FROM {Products} WHERE {code} LIKE ?search OR {name} LIKE ?search , where?search is a parameter from a text field. Managing more than some 50 or 100 search results in one single Collection is complicated and performs comparably slow. For this reason, the FlexibleSearch framework offers a paging mechanism.

To use this paging mechanism, use thesearch(...) method withFlexibleSearchQuery object as parameter. You have to set onFlexibleSearchQuery thesetNeedTotal totrue . If this parameter is set totrue , the FlexibleSearch framework splits the number of returned search results into pages. Using thestart andrange parameters, you can retrieve pages of search results. The following code snippet, for example, iterates over all the search results of the FlexibleSearch query, three at a time:


int start = 0;
final int range = 3;
int total;
 
String query = "SELECT {" + UnitModel.PK + "} FROM {"+ UnitModel._TYPECODE + "} ORDER BY " + UnitModel._TYPECODE;
final FlexibleSearchQuery fQuery = new FlexibleSearchQuery(query);
fQuery.setCount(range);
fQuery.setNeedTotal(true);
 
do
{
  fQuery.setStart(start);
  final SearchResult<LanguageModel> searchResult = flexibleSearchService.search(fQuery);
  total = searchResult.getTotalCount();
  start += range;
}
while(start < total);



Be aware that every navigation, either backward or forward, through a paged search result triggers a new search query on the database. Internally, the FlexibleSearch runs the query in full and uses an offset parameter to specify the portion of all search results to return. The fact that every navigation causes a database query has three major consequences:

Complex queries cause heavy load on the database:
Executing a simpleSELECT statement is rather fast, even with millions of search results. However, if your FlexibleSearch query requiresJOIN  orUNION to execute, load on the database (and, by consequence, response times) increases rapidly. As a rule of thumb, remember that the more different items are involved, the longer the execution time is. For example, the following table gives some short examples of some rather basic FlexibleSearch statements and the actual SQL queries triggered:


https://wiki.hybris.com/display/release5/FlexibleSearch#FlexibleSearch-Basics



你可能感兴趣的:(hybris-FlexibleSearch)