Skip to main content

Search term

GraphQL Query API search capabilities

Hii Retail provides certain GraphQL Query APIs where the user can leverage the built in query and response capabilities GraphQL provides. See more about this here.

This section describes the advanced capabilities provided for free-text searching.

Free-text search often requires different things based on the application where it is available. Below you can find those advanced concepts described in more detail.

Query String Syntax

A query string uses specific syntax to parse and split the provided query string based on operators (AND, OR). The default operator is OR.

A query string can be a single word — bottle or can — or a phrase, surrounded by double quotes — "bright and bubbly" — which searches for all the words in the phrase, in the same order.

A general recommendation is to NOT make heavy use of query string special syntax

For example, the wildcard and regular expressions should not be used unless it is absolutely necessary. A major reason is that an unfortunate implementation on the client side can result in heavy queries, slow response times, and bad user experience.

Invalid syntax in the searchTerm will return an error, and it is important that this is handled by the search components.

.keyword fields

It is also important to note the difference between a regular field name and the field name + a .keyword suffix.

A text field like name can be searched for individual words or phrases by using the field name alone - "bright and bubbly" would give you a hit if the exact phrase is present anywhere in the name field.

The name.keyword field takes the same input and keeps it as one large string, or as a single keyword. It is especially useful for structured content like email addresses, status codes, etc. - "bright and bubbly" would only give you a hit if the phrase is the exact content of the name.keyword field.

This allows you to get more performant hits on a specific phrase or word, if you know that it exists in this exact form in this particular field.

Example:

  • name: "Fizzy Drink 1" will search for this exact combination of words and would get a hit if this combination was an exact match for the entire name property, or as a part of the name property
  • name.keyword: "Fizzy Drink 1" would NOT get a hit unless this was the exact phrase of the name property.
  • The .keyword field is required if you need to use wildcard.

Supported Query Elements:

Reserved Characters

If you need to use any of the characters which function as operators in your query itself (and not as operators), then you should escape them with a leading backslash. The reserved characters are: + - = && || > < ! ( ) { } [ ] ^ " ~ * ? : \ /

When using JSON for the request body, two preceding backslashes (\) are required. Failing to escape these special characters correctly could lead to a syntax error which prevents your query from running. < and > can’t be escaped at all. Examples:

  • \(1\+1\)\=2 - searches for (1+1)=2
  • \\(1\\+1\\)\\=2 - the same query but when sent as JSON

Boolean Operators

The boolean operators which are supported are: + (indicates that a term must be present), - (indicates that a term must not be present), AND, OR, and NOT. Below are some examples:

  • bottle can +soda -fizzy - states that: soda must be present, fizzy must not be present, bottle and can are optional (their presence increases the relevance)
  • ((bottle AND soda) OR (can AND soda) OR soda) AND NOT fizzy - it's the same query as the previous one written with the help of the boolean operators AND, OR and NOT (also can be written as &&, || and !)

Field Names

  • businessUnitId.keyword:1-1 - where the businessUnitId field matches exactly the term 1-1
    • Note the use of keyword here. This allows an exact match to be found, but also increases performance of the query when an exact match is needed
  • status: ACTIVE - where the status field contains ACTIVE
  • name:(bottle OR flask) - where the name field contains bottle or flask
  • description: "heavy duty fabric" - where the description field contains the exact phrase "heavy duty fabric"
  • assortment\*:(IN_ASSORTMENT, C) - where any of the fields assortmentType or assortmentTags, etc. contains IN_ASSORTMENT or C
    • note how we need to escape the * with a backslash
  • _exists_:description - where the field description has any non-null value

Search Multiple Fields

  • businessUnitId:AW001 AND status:ACTIVE - where the businessUnitId field contains AW001 and status field contains ACTIVE.
    • The general form looks like this: field1:query_term OR/AND field2:query_term | ....

Wildcards - USE WITH CARE!

  • p?nk XX* - use ? to replace a single character, and * to replace zero or more characters

  • field:* - a pure wildcard would match a field with any value, including an empty value. It would not match if the field is missing or set with an explicit null value

    We do not support searching with a wildcard at the beginning of a word (eg. "*ing"). This has a heavy impact on performance thus it must not be used.

Regular Expressions - USE WITH CARE!

The supported regular expression syntax is explained in Regular expression syntax. Also, see some examples below:

  • name:/joh?n(ath[oa]n)/ - regular expression patterns can be embedded in the query string by wrapping them in forward-slashes.

Regular expressions like this one /.*n/ are not supported because of performance reasons. Such queries must not be used.

Fuzziness

  • quikc~ brwn~ foks~3 - fuzzy queries can specify a maximum edit distance for characters in a word.
    • The edit distance is the minimum number of operations required to change one word into the other.
    • The default edit distance is 2.
  • app*~1 - mixing fuzzy and wildcard operators is not supported.
    • When mixed, one of the operators is not applied. In this case, the fuzzy operator (~1) is not applied.

Proximity Searches

  • "fox quick"~5 - similar to fuzzy queries, but a proximity search allows us to specify a maximum edit distance of words in a phrase. A proximity query allows the specified words to be further apart or in a different order.

Ranges

Ranges can be specified for date, numeric, or string fields. Inclusive ranges are specified with square brackets [min TO max] and exclusive ranges with curly brackets {min TO max}. Examples:

  • validFrom:[2022-01-01 TO 2022-12-31] - all days in 2022
  • netContent:[1 TO 5] - numbers 1..5
  • assortmentTags:[A TO D] - AssortmentTags between A and D, including A and D
  • assortmentTags:{A TO D} - AssortmentTags between A and D, excluding A and D
  • netContent:[10 TO *] - numbers from 10 upwards
  • validTo:{* TO 2022-01-01} - dates before 2022
  • netContent:[1 TO 5} - numbers from 1 up to but not including 5
  • referencePriceConversionFactor:>1 - numbers greater than 1
  • referencePriceConversionFactor:>=1.5 - numbers equal or greater than 1.5
  • referencePriceConversionFactor:<1 - numbers less than 1
  • referencePriceConversionFactor:<=0.9 - numbers equal or less than 0.9
  • referencePriceConversionFactor:(>=1.1 AND <2) - numbers equal or greater than 1.1 and less than 2
  • netContent:[1 TO 5} - curly and square brackets can be combined
  • netContent:>=10, netContent:<=10 - you can use this syntax for ranges with one side unbounded
  • age:(>=10 AND <20) - you can join two clauses with an AND operator

Boosting

Use the boost operator ^ to make one term more relevant than another. The default boost value is 1, but can be any positive floating point number. Boosts between 0 and 1 reduce relevance. Below are some examples:

  • bottle^2 soda - find all items about soda, but we are especially interested in soda bottles
  • "soda bottle"^2 - boosts can also be applied to phrases
  • (soda can)^4 - boosts can also be applied to groups

Grouping

  • (bottle OR can) AND soda - multiple terms or clauses can be grouped together with parentheses to form sub-queries
  • status:(ACTIVE OR DISCONTINUED) name:(bright and bubbly)^2 - groups can be used to target a particular field, or to boost the result of a sub-query