Create a search interface with the Query API

The Query API provides search and suggest methods for building a search interface or embedding search results in an application.

For web applications with minimal requirements, consider using search widget. For more information, see Create a search interface with the search widget

Build a search interface

Building a minimal search interface requires several steps:

  1. Configure a search application
  2. Generate OAuth credentials for the application
  3. Query the index
  4. Display the query results

You can further enhance the search interface with features such as paging, sorting, filtering, facets, and auto-suggest.

Configure a search application

You must create at least one search application to associate with each search interface you create. A search application provides the default parameters for a query, such as the data sources to use, the sort order, filters, and facets to request. If needed, you can override these parameters using the query API.

For more information about search applications, refer to Customize the search experience in Cloud Search..

Generate OAuth credentials for the application

In addition to the steps in Configure access to the Google Cloud Search API, you also must generate OAuth credentials for the web application. The type of credentials you create depends on the context the API is used in.

Use the credentials to request authorization on behalf of the user. Use the scope https://www.googleapis.com/auth/cloud_search.query when requesting authorization.

For additional information about OAuth options and client libraries, see [Google Identity Platform](https://developers.google.com/identity/choose-auth{: .external target="_blank"}.

Query the index

Use the search method to perform searches against the index.

Every request must include two pieces of information: a text query to match items against and a searchApplicationId identifying the ID for the search application to use.

The following snippet shows a query to movie data source for the movie Titanic:

{
  "query": "titanic",
  "requestOptions": {
    "searchApplicationId": "searchapplications/<search_app_id>"
  },
}

Display query results

At a minimum, search interfaces are expected to display the item title as well as a link to the original item. You can further enhance the display of search results by leveraging additional information present in search results such as the snippet and metadata.

Handle supplemental results

By default, Cloud Search returns supplemental results when there are insufficient results for the user's query. The queryInterpretation field in the response indicates when supplemental results are returned. If only supplemental results are returned, InterpretationType is set to REPLACE. If a few results for the original query are returned along with supplemental results, InterpretationType is set to BLEND. In either case QueryInterpretation.Reason = NOT_ENOUGH_RESULTS_FOUND_FOR_USER_QUERY.

When some supplemental results are returned, consider providing text to indicate supplemental results were returned. For example, in the case of a REPLACE, you might display the string "Your search for your original query did not match any results. Showing results for similar queries.”

In the case of a BLEND, you might display the string "Your search for your original query did not match enough results. Including results for similar queries."

Handle people results

Cloud Search returns two types of "people results": documents related to a person whose name is used in the query and employee information for a person whose name is used in a query. The latter type of result is a function of Cloud Search's People Search feature and the results for such a query can be found in the structuredResults field of a query API response:

{
  "results": [...],
  "structuredResults": [{
    "person": {...}
  }]
}

Direct Reports Matching

Direct Reports Matching is a Cloud Search's People Search feature which lets users see the direct reports of a person in their organization. The result is available within the structuredResults field.

For queries about a person's manager or direct reports, the response has an assistCardProtoHolder within the structuredResults. The assistCardProtoHolder has a field called cardType which will be equal to RELATED_PEOPLE_ANSWER_CARD. The assistCardProtoHolder contains a card called relatedPeopleAnswerCard which contains the actual response. It contains the subject (the person who was included in the query) and relatedPeople which are the set of people related to the subject. The relationType field returns the value MANAGER or DIRECT_REPORTS.

The following code shows an example response for a direct reports matching query:

{
  "results": [],
  "structuredResults": [{
    "assistCardProtoHolder": {
      "extensions": {
        "@type": "type.googleapis.com/enterprise.topaz.sidekick.AssistCardProto",
        "cardMetadata": {
          "cardCategory": "ANSWER"
        },
        "cardType": "RELATED_PEOPLE_ANSWER_CARD",
        "relatedPeopleAnswerCard": {
          "subject": {
            "email": "AdamStanford@psincs-test01.newjnj.com",
            "displayName": "Adam Stanford"
            "manager": {
              "email": "simonsais@psincs-test01.newjnj.com"
            }
          },
          "relatedPeople": [{
            "email": "EdgarMountainRamirez@psincs-test01.newjnj.com",
            "displayName": "Edgar Mountain Ramirez"
          }, {
            "email": "FranciscoJoseMartinez@psincs-test01.newjnj.com",
            "displayName": "Francisco Jose Martinez"
          }],
          "relationType": "DIRECT_REPORTS",
        }
      }
    }
  }]
}

Turn off optimizations, including supplemental results

By default, optimizations, such as supplemental results, are enabled. You can, however turn off all optimizations or just supplemental results at both the search application and query level:

Highlight snippets

For returned items containing indexed text or HTML content, a snippet of the content is returned. This content helps users determine the relevancy of the returned item.

If query terms are present in the snippet, one or more match ranges identifying the location of the terms are also returned.

Use the matchRanges to highlight the matching text when rendering the results. The following javascript example converts the snippet into HTML markup with each matching range wrapped in a <span> tag.

function highlightSnippet(snippet) {
  let text = snippet.snippet;
  let formattedText = text;
  if (snippet.matchRanges) {
    let parts = [];
    let index = 0;
    for (let match of snippet.matchRanges) {
      let start = match.start || 0; // Default to 0 if omitted
      let end = match.end;
      if (index < start) { // Include any leading text before/between ranges
        parts.push(text.slice(index, start));
      }
      parts.push('<span class="highlight">');
      parts.push(text.slice(start, end));
      parts.push('</span>');
      index = end;
    }
    parts.push(text.slice(index)); // Include any trailing text after last range
    formattedText = parts.join('');
  }
  return formattedText;
}

Given the snippet:

{
  "snippet": "This is an example snippet...",
  "matchRanges": [
    {
      "start": 11,
      "end": 18
    }
  ]
}

The resulting HTML string is:

This is an <span class="highlight">example</span> snippet...

Display metadata

Use the metadata field to display additional information about the returned item that may be relevant to users. The metadata field includes the createTime and updateTime of the item as well as any returnable structured data associated with the item.

To display the structured data, use the displayOptions field. The displayOptions field contains the display label for the object type and a set of metalines. Each metaline is an array of display labels and value pairs as configured in the schema.

Retrieve additional results

To retrieve additional results, set the start field in the request to the desired offset. You can adjust the size of each page with the pageSize field.

To display the number of returned items or to display paging controls to page through returned items, use the resultCount field. Depending on the size of the result set, either the actual value or an estimated value is provided.

Sort results

Use the sortOptions field to specify the order of returned items. The sortOptions value is an object with two fields:

  • operatorName — an operator for the structured data property to sort by. For properties with multiple operators, you can only sort using the main equality operator.
  • sortOrder — the direction to sort, either ASCENDING or DESCENDING.

Relevance is also used as the secondary sort key. If no sort order is specified in a query, results are ranked only by relevance.

"sortOptions": {
  "operatorName": "priority",
  "sortOrder": "DESCENDING"
}

Add filters

In addition to query expressions, you can further restrict results by applying filters. You can specify filters both in the search application as well as in the search request.

To add filters in a request or search application, add the filter in the dataSourceRestrictions.filterOptions[] field.

There are 2 primary ways to further filter a data source:

  • Object filters, via the filterOptions[].objectType property — restricts matching items to the specified type as defined in a custom schema.
  • Value filters — restricts matching items based on a query operator and supplied value.

Composite filters allow combining multiple value filters into logical expressions for more complex queries.

In the movie schema example, you could apply an age constraint based on the current user and restrict the available movies based on the MPAA rating.

{
  "query": "adventure",
  "requestOptions": {
    "searchApplicationId": "<search_app_id>"
  },
  "dataSourceRestrictions": [
    {
      "source": {
        "name": "datasources/<data_source_id>"
      },
      "filterOptions": [
        {
          "objectType": "movie",
          "filter": {
            "compositeFilter": {
              "logicOperator": "AND"
              "subFilters": [
                {
                  "compositeFilter": {
                  "logicOperator": "OR"
                  "subFilters": [
                    {
                      "valueFilter": {
                        "operatorName": "rated",
                        "value": {
                          "stringValue": "G"
                        }
                      }
                    },
                    {
                      "valueFilter": {
                        "operatorName": "rated",
                        "value": {
                          "stringValue": "PG"
                        }
                      }
                    }
                  ]
                }
              ]
            }
          }
        }
      ]
    }
  ]
}

Refine results with facets

Facets are indexed properties that represent categories for refining search results. Use facets to help users interactively refine their queries and find relevant items faster.

Facets can be defined in your search application. and overridden by settings in your query.

When requesting facets, Cloud Search computes the most-frequent values for the requested properties among the matching items. These values are returned in the response. Use these values to construct filters that narrow the results on subsequent queries.

The typical interaction pattern with facets is:

  1. Make an initial query specifying which properties to include in the facet results.
  2. Render the search and facet results.
  3. User selects one or more facet values to refine the results.
  4. Repeat the query with a filter based on the selected values.

For example, to enable refinement of movie queries by year and MPAA rating, include the facetOptions property in the query.

"facetOptions": [
  {
    "sourceName": "datasources/<data_source_id>",
    "operatorName": "year"
  },
  {
    "sourceName": "datasources/<data_source_id>",
    "operatorName": "rated"
  }
]

Facet results with integer-based fields

You can also facet request results with integer-based fields. For example, you might mark an integer property called book_pages as facetable to refine results for a search about books with "100-200" pages.

When you set up your integer property field schema, set isFacetable to true and add corresponding bucketing options to the integerPropertyOptions. This ensures that every integer-facetable property has default bucketing options defined.

When defining bucketing options logic, supply an array of incremental values signifying ranges. For example, if the end user specifies ranges as 2, 5, 10, 100, then facets for <2, [2-5), [5-10), [10-100), >=100 are calculated.

You can override integer-based facets by defining the same bucketing options to facetOptions in the request. If required, Cloud Search uses the bucketing options defined in the schema when neither the search application nor query request have facet options defined. Facets defined in the query take precedence over facets defined in the search application, and facets defined in the search application take precedence over facets defined in the schema.

Facet results by document size or date

You can use reserved operators to refine search results by document's file size, measured in bytes, or by when a document was created or modified. You don't need to define a custom schema, but you do need to specify the operatorName value in your search application's FacetOptions.

  • For faceting by document size, use itemsize and define bucketing options.
  • For faceting by document creation date, use createddatetimestamp.
  • For faceting by document modified date, use lastmodified.

Interpreting facet buckets

The facetResults property in the search query response includes the user's exact filter request in the filter field for each bucket.

For facets that aren't based on integers, facetResults includes an entry for each requested property. For each property, a list of values or ranges, called buckets, is provided. The most-frequently occurring values appear first.

When a user selects one or more values to filter on, construct a new query with the selected filters and query the API again.

Add suggestions

Use the suggest API to provide auto-completion for queries based on the user's personal query history as well as contacts and their document corpus.

For example, the following call gives suggestions for the partial phrase jo.

{
  "query": "jo",
  "requestOptions": {
    "searchApplicationId": "<search_app_id>",
    "peoplePhotoOptions": {
      "peoplePhotoUrlSizeInPx": 32
    },
    "timeZone": "America/Denver"
  }
}

You can then display the resulting suggestions as appropriate for your application.