使用 Query API 创建搜索界面

Query API 提供搜索和建议方法,用于构建搜索界面或在应用中嵌入搜索结果。

对于要求极低的 Web 应用,可以考虑使用搜索微件。 如需了解详情,请参阅使用搜索微件创建搜索界面

构建搜索界面

构建一个最小的搜索界面需要执行以下几个步骤:

  1. 配置搜索应用
  2. 为应用生成 OAuth 凭据
  3. 查询索引
  4. 显示查询结果

此外,您可以进一步增强搜索界面,为其添加分页、排序、过滤、属性和自动建议等功能。

配置搜索应用

您必须创建至少一个搜索应用以便关联您创建的每个搜索界面。搜索应用为查询提供默认参数,例如要使用的搜索数据源、排序顺序、过滤条件和要请求的构面。如果需要,您可以使用 Query API 替换这些参数。

如需详细了解搜索应用,请参阅自定义 Cloud Search 的搜索体验

为应用生成 OAuth 凭据

除了执行配置对 Google Cloud Search API 的访问权限中的步骤以外,您还必须为 Web 应用生成 OAuth 凭据。您创建的凭据类型取决于使用 API 的上下文。

使用这些凭据即可代表用户请求授权。请求授权时,请使用范围 https://www.googleapis.com/auth/cloud_search.query

如需详细了解 OAuth 选项和客户端库,请参阅 [Google Identity Platform](https://developers.google.com/identity/choose-auth{: .external target="_blank"}。

查询索引

使用 search 方法对索引执行搜索。

每个请求必须包含两条信息:用于匹配项的 query 文本,以及标识要使用的搜索应用 ID 的 searchApplicationId

以下代码段展示了对电影《泰坦尼克号》的电影数据源的查询:

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

显示查询结果

搜索界面至少应显示 title 项以及指向原始项的链接。您可以利用搜索结果中包含的其他信息(例如摘要和元数据)来进一步增强搜索结果的显示效果。

处理补充结果

默认情况下,如果用户的查询没有足够的结果,Cloud Search 会返回补充结果。响应中的 queryInterpretation 字段指示何时返回补充结果。如果仅返回补充结果,则将 InterpretationType 设置为 REPLACE。如果系统同时返回原始查询的部分结果和补充结果,则 InterpretationType 会设为 BLEND。无论是哪种情况,QueryInterpretation.Reason = NOT_ENOUGH_RESULTS_FOUND_FOR_USER_QUERY

返回一些补充结果时,不妨提供一些文字来指明返回了补充结果。例如,对于 REPLACE,您可以显示字符串“您的原始查询搜索没有匹配到任何结果。显示类似查询的搜索结果。”

对于 BLEND,您可以显示字符串“您的原始查询的搜索结果不够多。包含类似查询的结果。”

处理人员搜索结果

Cloud Search 会返回两种类型的“人物搜索结果”:与查询中所用姓名对应的人物相关的文档,以及与查询中所用姓名对应的员工信息。后一种结果是 Cloud Search 的“人物搜索”功能的函数,您可以在查询 API 响应的 structuredResults 字段中找到此类查询的结果:

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

直接下属匹配

“直接下属匹配”是 Cloud Search 的“人员搜索”功能,可让用户查看组织中某位人员的直接下属。结果可在 structuredResults 字段中获取。

对于有关用户经理或直接下属的查询,响应中的 structuredResults 中会包含 assistCardProtoHolderassistCardProtoHolder 有一个名为 cardType 的字段,该字段将等于 RELATED_PEOPLE_ANSWER_CARDassistCardProtoHolder 包含一个名为 relatedPeopleAnswerCard 的卡片,其中包含实际响应。它包含 subject(查询中包含的用户)和 relatedPeople(与主题相关的一组用户)。relationType 字段会返回值 MANAGERDIRECT_REPORTS

以下代码显示了与查询匹配的直接报告的示例响应:

{
  "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",
        }
      }
    }
  }]
}

关闭优化功能,包括补充结果

默认情况下,优化功能(例如补充结果)处于启用状态。不过,您可以在搜索应用和查询级别关闭所有优化,也可以仅关闭补充结果:

突出显示片段

对于包含已编入索引的文本或 HTML 内容的返回项,界面将返回内容摘要。此内容可帮助用户确定返回项的相关性。

如果摘要中存在查询字词,则界面还会返回标识字词位置的一个或多个匹配范围。

在呈现结果时,可使用 matchRanges 突出显示匹配的文本。以下 javascript 示例将摘要转换为 HTML 标记,每个匹配范围都包含在 <span> 标记中。

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;
}

对于下面的片段:

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

生成的 HTML 字符串为:

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

显示元数据

使用 metadata 字段显示可能与用户相关的返回项的其他信息。metadata 字段包含返回项的 createTimeupdateTime,以及与该项关联的任何可返回的结构化数据。

如需显示这些结构化数据,请使用 displayOptions 字段。displayOptions 字段包含对象类型的显示标签和一组 metalines。每个 metaline 都是架构中配置的显示标签和值对的数组。

检索其他结果

如要检索其他结果,请将请求中的 start 字段设置为所需的偏移量。您可以使用 pageSize 字段调整每个页面的大小。

如要显示返回项数量或显示分页控件以对返回项进行分页,请使用 resultCount 字段。提供的值可能为实际值,也可能为估计值,具体取决于结果集的大小。

对结果排序

使用 sortOptions 字段指定返回项的顺序。sortOptions 值是一个包含两个字段的对象:

  • operatorName - 用于排序的结构化数据属性的运算符。 对于具有多个运算符的属性,只能使用主相等性运算符进行排序。
  • sortOrder - 排序方向,可设为 ASCENDINGDESCENDING

相关性也会用作辅助排序键。如果查询中未指定排序顺序,则结果仅按相关性排序。

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

添加过滤条件

除了查询表达式之外,您还可以应用过滤条件来进一步限制结果。您可以在搜索应用和搜索请求中指定过滤条件。

如要在请求应用或搜索应用中添加过滤条件,请使用 dataSourceRestrictions.filterOptions[] 字段。

您可以通过以下两种主要方法进一步过滤数据源:

  • 对象过滤器(通过 filterOptions[].objectType 属性)- 将匹配项限制为自定义架构中定义的指定类型。
  • 值过滤器 - 根据查询运算符和提供的值限制匹配项。

复合过滤器允许将多个值过滤器合并到逻辑表达式中,以实现更复杂的查询。

在电影架构示例中,您可以针对当前用户应用年龄限制,并根据 MPAA 分级限制可观看的电影。

{
  "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"
                        }
                      }
                    }
                  ]
                }
              ]
            }
          }
        }
      ]
    }
  ]
}

使用属性优化结果

属性是指已编入索引的属性,表示用于优化搜索结果的类别。使用属性可以帮助用户以交互的方式优化查询,更快地查找相关项。

您可以在搜索应用中定义属性,并通过查询中的设置来替换属性。

在请求属性时,Cloud Search 会在匹配项中计算所请求属性最常出现的值。这些值会在响应中返回。您可以使用这些值构造过滤器,以便在后续查询中缩小结果范围。

属性的典型交互模式如下:

  1. 进行初始查询,指定要在属性结果中包含哪些属性。
  2. 呈现搜索和属性结果。
  3. 用户选择一个或多个属性值以优化结果。
  4. 根据所选的值构造过滤器,然后使用该过滤器重复查询。

例如,要根据年份和 MPAA 分级优化电影查询,请在查询中添加 facetOptions 属性。

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

包含基于整数的字段的构面结果

您还可以使用基于整数的字段对请求结果进行细分。例如,您可以将名为 book_pages 的整数属性标记为可分面,以便对“页数为 100-200”的图书搜索结果进行优化。

设置整数属性字段架构时,请将 isFacetable 设置为 true,并将相应的分桶选项添加到 integerPropertyOptions。这样可确保为每个整数键值对属性定义了默认的分桶选项。

在定义分桶选项逻辑时,请提供一个表示范围的增量值数组。例如,如果最终用户将范围指定为 2, 5, 10, 100,系统会计算 <2[2-5)[5-10)[10-100)>=100 的切面。

您可以在请求中为 facetOptions 定义与基于整数的多个维度相同的分桶选项,以替换基于整数的多个维度。如果搜索应用和查询请求都未定义细分选项,Cloud Search 会视需要使用架构中定义的分桶选项。在查询中定义的维度优先于在搜索应用中定义的维度,在搜索应用中定义的维度优先于在架构中定义的维度。

按文档大小或日期对结果进行细分

您可以使用预留运算符按文档的文件大小(以字节为单位)或文档的创建或修改时间来优化搜索结果。您无需定义自定义架构,但需要在搜索应用的 FacetOptions 中指定 operatorName 值。

  • 如需按文档大小进行细分,请使用 itemsize 并定义分桶选项。
  • 如需按文档创建日期进行切片,请使用 createddatetimestamp
  • 如需按文档修改日期进行切片,请使用 lastmodified

解读构面范围

搜索查询响应中的 facetResults 属性包含每个 bucketfilter 字段中的用户确切过滤条件请求。

对于非基于整数的面,facetResults 包含每个请求属性的条目。对于每个属性,系统会提供一个值或范围列表(称为 buckets)。最常出现的值会优先显示。

当用户选择一个或多个值进行过滤时,使用所选过滤器构造新查询并再次查询 API。

添加建议

使用建议 API 根据用户的个人查询历史记录以及联系人及其文档语料库为查询提供自动补全功能。

例如,以下调用为部分短语 jo 提供了建议。

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

然后,您可以显示适合您的应用的建议。