This is the documentation for Recommendations AI, Retail Search, and the new Retail console.

Query and paginate

This page describes basic querying and using pagination with Retail Search.

Never cache personalized results from an end user, and never return personalized results to a different end user.

Querying tutorial

This tutorial shows you how to send a simple search query to the Retail service and analyze the response.


For step-by-step guidance on this task directly in Cloud Shell Editor, click Guide me:

Guide me


The following sections take you through the same steps as clicking Guide me.

Pagination tutorial

This tutorial shows you how to control pagination in your search request.


For step-by-step guidance on this task directly in Cloud Shell Editor, click Guide me:

Guide me


The following sections take you through the same steps as clicking Guide me.

Evaluate search results

Before you update your website code to request search results, you can preview search results to confirm that your serving config is working as you expect.

For more information about serving configs, see Serving configurations.

You can preview serving config results either from the Evaluate page, or by going to a serving config's Details page in the console and clicking its Evaluate tab. The following steps show you how to preview from the Evaluate page.

To preview search results returned by your serving configuration:

  1. Go to the Retail Evaluate page in the Google Cloud console.

    Go to the Evaluate page

  2. Click the Search tab.

  3. Select the serving configuration you want to preview.

  4. Select the [catalog branch][catalog-branch] that contains the catalog you want to preview.

  5. (Optional) Enter a visitor ID to preview search results for that user.

  6. (Optional) Enter a search time to preview search results that would appear at the specified time.

    For example, if you have promoted certain products for Black Friday, you can see results as they would appear on that day.

  7. (Optional) Select facets to display alongside the search results and click OK to apply them.

    The facets you select are used to generate a list of facet filters that appear under Add facets after you perform the initial search. These facet filters can include facets other than those you select in this step, such as dynamic facets.

  8. Enter a search query to preview search results for that query.

  9. Click Search preview or press enter in any input field to see the search results.

    Search results are displayed with their available thumbnail images.

    If your search triggers a redirect control, a notice appears that displays the redirect URI.

  10. (Optional) Click the Grid icon or the List icon to switch how your search results are displayed in preview.

  11. (Optional) If you selected facets to appear alongside your results, select one or more facet values from the facets list to filter results by those values. The results are automatically updated upon selection.

    When you select multiple values of the same facet, they are applied as an OR operator would be, and values across different facets are applied as an AND operator would be. For example, after selecting the facets "color" and "material", you might then filter your search results by selecting the color values "blue" and "gold", and the material values "cotton" and "polyester". Your search results results must have either "blue" or "gold" as an attribute, and must also have either "cotton" or "polyester" as an attribute.

To see the Details page for the serving config you're previewing, click View serving config under the Select serving config field.

Query

A minimal version of a search request requires placement and query.

Java

public static SearchResponse searchProducts(String query) throws IOException, InterruptedException {
  SearchServiceClient searchClient = getSearchServiceClient();

  SearchRequest searchRequest = SearchRequest.newBuilder()
      .setPlacement(DEFAULT_SEARCH_PLACEMENT_NAME)
      .setBranch(DEFAULT_BRANCH_NAME)
      .setVisitorId(VISITOR_ID)
      .setQuery(query)
      .build();

  SearchResponse response = searchClient.search(searchRequest).getPage().getResponse();

  searchClient.shutdownNow();
  searchClient.awaitTermination(2, TimeUnit.SECONDS);

  return response;
}

Python

def search_products(query: str):
    search_request = SearchRequest()
    search_request.placement = default_search_placement
    search_request.branch = default_catalog
    search_request.query = query
    search_request.filter = build_isolation_filter(test_id)
    search_request.visitor_id = visitor_id

    print(search_request)

    return get_search_service_client().search(search_request)

By default, a reasonable number of results ordered by relevance is returned.

To get product attributes returned with the search response, make sure to provide attribute values when you import your catalog data. Product has predefined system attributes such as brand, color, and size that you can provide values for. You can also include custom attributes that you define with Product.attributes.

Paginate

We recommend using pagination to decrease the lookup time and the size of the responses being sent over the wire.

To jump from one page to another, use either page_token or offset, according to your use case.

To jump to the next page, you could use page_token. For example, suppose you send the following SearchRequest.

JSON

{
  placement: 'projects/PROJECT_NUMBER/locations/global/catalogs/default_catalog/placements/default_search'
  visitor_id: 'VISITOR_ID'
  query: 'shoes'
  page_size: 5
}

From SearchResponse, you can get the resulting products with top 5 relevance, along with a next_page_token.

JSON

{
  results: [
    products{...}, products{...}, products{...}, products{...}, products{...}
  ]
  next_page_token: "wY4ETNkBDOlVjZ0YWLzUmM40SMhVjMtADMwATL5UGN5MGZlVDJaIQ5LaYsQUw9fC6lIwgE1EgC"
  total_size: 100
  search_token: "NtQKDAiXt4_3BRDCg_jnARABGiQ1ZWRjOTRlOC0wMDAwLTI1YTEtODJlMy1mNGY1ZTgwZDUxOGM"
}

To get the result products with the next 5 relevance (6th to 10th), you would set page_token using the same placement, visitor_id, and query as next_page_token from the previous SearchResponse.

Java

public static SearchResponse searchProducts_withNextPageToken(String query, int pageSize)
    throws IOException, InterruptedException {
  SearchServiceClient searchClient = getSearchServiceClient();

  SearchRequest firstRequest = SearchRequest.newBuilder()
      .setPlacement(DEFAULT_SEARCH_PLACEMENT_NAME)
      .setBranch(DEFAULT_BRANCH_NAME)
      .setVisitorId(VISITOR_ID)
      .setQuery(query)
      .setPageSize(pageSize)
      .build();
  SearchResponse firstResponse = searchClient.search(firstRequest).getPage()
      .getResponse();

  SearchRequest secondRequest = SearchRequest.newBuilder()
      .setPlacement(DEFAULT_SEARCH_PLACEMENT_NAME)
      .setBranch(DEFAULT_BRANCH_NAME)
      .setVisitorId(VISITOR_ID)
      .setQuery(query)
      .setPageSize(pageSize)
      .setPageToken(firstResponse.getNextPageToken())
      .build();

  SearchResponse response = searchClient.search(secondRequest).getPage().getResponse();

  searchClient.shutdownNow();
  searchClient.awaitTermination(2, TimeUnit.SECONDS);

  return response;
}

In this example, SearchRequest looks like this:

JSON

{
  placement: 'projects/PROJECT_NUMBER/locations/global/catalogs/default_catalog/placements/default_search'
  visitor_id: 'VISITOR_ID'
  query: 'shoes'
  page_size: 5
  page_token: "wY4ETNkBDOlVjZ0YWLzUmM40SMhVjMtADMwATL5UGN5MGZlVDJaIQ5LaYsQUw9fC6lIwgE1EgC"
}

In some other cases, instead of navigating from page to page or getting results with top relevance, you could directly jump to a particular position with offset.

Java

public static SearchResponse searchProducts_withOffset(String query, int pageSize,
    int offset) throws IOException, InterruptedException {
  SearchServiceClient searchClient = getSearchServiceClient();

  SearchRequest searchRequest = SearchRequest.newBuilder()
      .setPlacement(DEFAULT_SEARCH_PLACEMENT_NAME)
      .setBranch(DEFAULT_BRANCH_NAME)
      .setVisitorId(VISITOR_ID)
      .setQuery(query)
      .setPageSize(pageSize)
      .setOffset(offset)
      .build();

  SearchResponse response = searchClient.search(searchRequest).getPage().getResponse();

  searchClient.shutdownNow();
  searchClient.awaitTermination(2, TimeUnit.SECONDS);

  return response;
}

Python

def search_products_with_offset(query: str, _offset: int, page_size=10):
    search_request = SearchRequest()
    search_request.placement = default_search_placement
    search_request.branch = default_catalog
    search_request.query = query
    search_request.filter = build_isolation_filter(test_id)
    search_request.page_size = page_size
    search_request.offset = _offset
    search_request.visitor_id = visitor_id

    print(search_request)

    return get_search_service_client().search(search_request)

For example, if you want the tenth page of the results when the page size is 5, then you could set the offset to be 45, which is calculated by (10 - 1) * 5.

JSON

{
  placement: 'projects/PROJECT_NUMBER/locations/global/catalogs/default_catalog/placements/default_search'
  visitor_id: 'VISITOR_ID'
  query: 'shoes'
  page_size: 5
  offset: 45
}