基础知识 java
该FlexibleSearch是内置采用hybris Commerce Suite的一个强大的检索语言。它能采用hybris商务套件使用基于SQL语法搜索类型和物品。
sql
一个FlexibleSearch语句的执行发生在两个阶段: 数据库
pre-parsing(预解析)到一个SQL-compliant语句中和运行这个语句在数据库上 api
在预解析阶段,FlexibleSearch框架解析FlexibleSearch语法到SQL-compliant里。下面的两个代码段表现出一个FlexibleSearch查询和这个FlexibleSearch语句查询的结果,这是在数据库上执行的语句: app
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框架解析类型和数据库表自动依赖关系并指定必要UNIONS和JOINS在哪里。类型系统和数据库表示之间的整个转换过程是自动进行的。要访问一个类型中FlexibleSearch查询,请用花括号{and},如类型代码: less
SELECT * FROM {Product}
采用hybris Commerce Suite的在某一用户账户的上下文中执行FlexibleSearch查询,使用一个会话。由于不一样的用户账户访问在采用hybris商务套件的不一样项目,搜索结果的数量取决于用户的账户。搜索结果的数目被按类型的访问权限定义(这些仅影响采用hybris管理控制台的搜索结果),限制,目录版本和类别。 flex
更多的特权用户账户是,在更多的搜索结果FlexibleSearch产量在用户账户的上下文中。默认状况下,分配给会话的用户账户是匿名的,因此任何FlexibleSearch查询返回的搜索结果相匹配的默认匿名账户。 ui
匿名不一样用户账户的状况下运行从FlexibleSearch查询,该会话须要被分配给不一样的用户账户,如: this
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>字段中的值指定要返回的数据库列。星号(*)将返回全部数据库列,如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的状况下,类型搜索是Product和VariantProduct。正如商务部的hybris一套房类型定义为一个项目,所以有一个主键(PK),在FlexibleSearch检索全部类型的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')
避免空间搜索条件条款 必定要避免空间的开始和结束搜索条件来看,随着由于= '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 */ )
下面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的API的FlexibleSearch
用使用的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);
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();慎重
传递参数
传递参数,建立一个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的不是Collection的Collection:
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的一种手段。在HMC的ViewType表示称为报表定义。该SavedQuery实例是HMC仅表示,它必须指定一个与resultType和仅适用于与resultType并与resultType亚型搜索。它适用于全部类型的电子商务的hybris套房。
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).
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.
Go to the Creating Report Definitions Using the hybris Management Console document for details on how to create a Report Definition using the hMC.
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