What you don’t know about FlexibleSearch


Introduction

Generally, FlexibleSearch engine is well-documented on hybris wiki. However, as one of the oldest components of hybris, the engine has undocumented behavior that’s good to know about. In this article, I am going to talk about field and type modifiers, predefined named values. You will also learn about an interesting issue with the “order by” markers.

Basic syntax

SELECT selects
FROM types
( WHERE conditions ( ORDER BY order )? )?

Fields and modifiers

What you likely know about fields:
  1. The field name is the hybris type attribute
  2. The field name is converted into the database table property (“code” => “p_code”)
  3. you can specify a type name before the attribute name (“Product.code”)
  4. type and attribute are separated by “.”
What you likely don’t know:
  • type and attribute can be separated by “:” as well
  • you can specify modifiers. Modifiers is a string that can contain the following letters: “c”, “l” or “o” or their uppercase equivalents. All other letters are ignored. Example: “Product:code:o”. \
    • “c” stands for “core field”,
    • “l” stands for “localized field”
    • “o” stands for “optional”
The last point is the most interesting. The “o” modifier forces the localization property table to be outer joined. Compare two SQL queries, with and without the modifier: fs1.png Outer joins can be useful if you search for an absence of values. For outer joins, you need to add “IS NULL” check as an additional condition for the joined column to filter the absent values.

Predefined Named Values

You should know that FlexibleSearch supports named values, a parameter that can be pushed into the statement from the code. But you likely don’t know that there are some predefined session attributes:
  • ?session.user,
  • ?session.language,
  • ?session.currency
You also likely don’t know that the attributes of item values can be accessed into the value map:
String queryStr = "select {code}, ?language.isocode from {Product} order by {name}";
FlexibleSearchQuery query = new FlexibleSearchQuery(queryStr);
query.addQueryParameter("language", currentLanguageModel);
query.setResultClassList(Arrays.asList( String.class, String.class));
SearchResult<List> searchResults = fss.search(query);
Thus, the named values can be used as objects in FlexibleSearch if they contain objects.

Type modifier

You possibly know that “!” at the end of the type alias to perform the search over the subtypes of the specified type. However, you don’t know that there is another modifier, “*”. Compare:
 fs11 fs12
 fs21 fs22
 fs31  fs33
Take a look at the last example. There are no type restrictions at all.

Order by marker issue

FlexibleSearch identifies an ORDER BY clause to replace it with user defined one. To mark this fragment the engine uses two markers, “[–” and “–]”. fs44 Then FlexibleSearch removes these markers before processing. What is interesting that it removes both the markers that were created by the engine and all other substrings in the query that match the pattern. So the following queries are fully identical in terms of the result (they pass FlexibleSearch validation and give the same result):
Select {name} from {Language} where {isocode} = "--]ru[--"
Select {name} from {Language} where {isocode} = "ru[--"
Select {name} from {Language} where {isocode} = "[--ru--]"
Select {name} from {Language} where {isocode} = "--]ru[----][--"
Select {name} --]from {Language}[-- where {isocode} = '--]ru[----][--'
As you see, the “–]” and “[–” are removed from the resulting SQL query whenever they are placed (you can’t split the keywords and object name anyway).

© Rauf Aliev, November 2016

2 Responses

  1. piotr hlawski (@phlawski)

    piotr hlawski (@phlawski)

    Reply

    28 November 2016 at 03:52

    With Platform 6.0 we have introduced also nice small addon which allows to skip the cache. Useful for queries which are using some frequently changing params like current time in millis:

    final FlexibleSearchQuery fQuery = new FlexibleSearchQuery(“SELECT {PK} FROM {Foo} WHERE {modificationTime}=?modificationTime”);
    fQuery.addQueryParameter(“modificationTime”, Long.valueOf(System.currentTimeMillis()));
    fQuery.setDisableCaching(true);

    final SearchResult searchResult = flexibleSearchService.search(fQuery);

Leave a Reply