基礎知識 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