Filter and order results

This page describes filtering and ordering with search.

Semantic filtering optimizes non-default sorting

AI Commerce Search is designed to show a wide variety of results, including marginally relevant items that are popular or trending. This is effective in default searches (sorted by relevance), but in non-default searches that use the order_by feature, such as sort-by-price, less relevant items can appear more prominently due to lower price, for example.

To ameliorate this effect, AI Commerce Search has introduced semantic embedding-based filtering to remove these less relevant items from non-default search results, improving user experience.

This intended behavior could, however, lead fewer search results overall. Disabling filtering can impact search-result quality. So if fewer search results is of concern, contact support.

Filtering tutorial

This tutorial demonstrates the filtering feature. It lets you fine-tune search requests according to your or your customer's needs. You can filter by single or multiple fields, filter by text or numeric fields, or both. You can use an expression language to construct a predicate for each field or combine different expressions using logical operators. For example, a shopper looking for shoes can use filters to narrow their search to their preferred brand and color.


To follow step-by-step guidance for this task directly in the Cloud Shell Editor, click Guide me:

Guide me


Ordering tutorial

This tutorial shows how to order items in a search response. When an end user looks for a product on your site, they are shown results ordered by multiple fields. For example, a user is searching for a dress with the best price and discount. Price and discount are multiple fields here. The user will see the dresses ordered by price, and for the dresses with the same price, ordered by discount.


To follow step-by-step guidance for this task directly in the Cloud Shell Editor, click Guide me:

Guide me


Example dataset

This page uses the following dataset as an example. Only the fields necessary for the example are included.

Filter

Java

import com.google.cloud.retail.v2.SearchRequest;
import com.google.cloud.retail.v2.SearchResponse;
import com.google.cloud.retail.v2.SearchServiceClient;

public static void searchFilteredProducts(String query, int pageSize,
    String filter) throws IOException, InterruptedException {
  SearchRequest searchRequest = SearchRequest.newBuilder()
      .setPlacement(DEFAULT_SEARCH_PLACEMENT_NAME)
      .setBranch(DEFAULT_BRANCH_NAME)
      .setVisitorId(VISITOR_ID)
      .setQuery(query)
      .setPageSize(pageSize)
      .setFilter(filter)
      .build();

  try (SearchServiceClient searchClient = SearchServiceClient.create()) {
    SearchResponse response = searchClient.search(searchRequest).getPage().getResponse();
    System.out.println("Search response: " + searchResponse);
  }
}

The filter expression syntax can be summarized by the following EBNF:

  # A single expression or multiple expressions that are joined by "AND" or "OR".
  filter = expression, { " AND " | "OR", expression };

  # Expressions can be prefixed with "-" or "NOT" to express a negation.
  expression = [ "-" | "NOT " ],
    # A parenthetical expression.
    | "(", expression, ")"
    # A simple expression applying to a text field.
    # Function "ANY" returns true if the field contains any of the literals.
    ( text_field, ":", "ANY", "(", literal, { ",", literal }, ")"
    # A simple expression applying to a numerical field. Function "IN" returns true
    # if a field value is within the range. By default, lower_bound is inclusive and
    # upper_bound is exclusive.
    | numerical_field, ":", "IN", "(", lower_bound, ",", upper_bound, ")"
    # A simple expression that applies to a numerical field and compares with a double value.
    | numerical_field, comparison, double );

  # A lower_bound is either a double or "*", which represents negative infinity.
  # Explicitly specify inclusive bound with the character 'i' or exclusive bound
  # with the character 'e'.
  lower_bound = ( double, [ "e" | "i" ] ) | "*";

  # An upper_bound is either a double or "*", which represents infinity.
  # Explicitly specify inclusive bound with the character 'i' or exclusive bound
  # with the character 'e'.
  upper_bound = ( double, [ "e" | "i" ] ) | "*";

  # Supported comparison operators.
  comparison = "<=" | "<" | ">=" | ">" | "=";

  # A literal is any double quoted string. You must escape backslash (\) and
  # quote (") characters.
  literal = double quoted string;

  text_field = see the table below;

  numerical_field = see the table below;

The supported textual fields are summarized in the following table.

field