使用 Query API 创建搜索界面

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

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

构建搜索界面

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

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

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