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).

2 comments

  1. 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);

    Liked by 2 people

    1. Thank you, Piotr!

      Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: