hybris-FlexibleSearch

基礎知識 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框架解析類型和數據庫表自動依賴關係並指定必要UNIONSJOINS在哪裏。類型系統和數據庫表示之間整個轉換過程是自動進行的要訪問一個類型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>


<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

本站公眾號
   歡迎關注本站公眾號,獲取更多信息