搜索应用程序客户端指南
Elastic Stack Serverless
本文档是一个操作指南,介绍如何使用 搜索应用程序 和 搜索应用程序客户端 构建搜索体验。 该客户端是一个 JavaScript 库,旨在在浏览器中使用。 您需要将此库集成到您的 Web 应用程序中,以简化对搜索应用程序的查询。
本指南假设您想构建一个具有以下搜索功能的 Web 应用程序
- 具有自定义相关性的搜索栏和结果
- 控制结果的呈现方式,例如包含/排除字段和突出显示匹配项
- UI 控件,例如分面、过滤器、排序、分页
您可以将搜索应用程序视为持久化 Elasticsearch 更改的“服务器端”。 您的 Web 应用程序充当查询搜索应用程序的“客户端”。 您将对搜索应用程序和 Web 应用程序进行编辑以完成实施。
要遵循本指南,您需要
一个满足运行搜索应用程序的先决条件的 Elastic 部署。
- 如果您没有 Elastic 部署,请在 Elastic Cloud 上开始免费试用。
一个 搜索应用程序。
一个 Web 应用程序,用于使用 搜索应用程序客户端 查询您的搜索应用程序。
安装 使用 npm、yarn 或 CDN 的客户端。
选项 1:使用包管理器
要使用 npm 安装客户端,请运行以下命令
npm install @elastic/search-application-client
要使用 yarn 安装客户端,请运行以下命令
yarn add @elastic/search-application-client
选项 2:使用带有 HTML <script>
标记的 CDN
或者,您可以使用 CDN 安装客户端。 将以下 <script>
标记添加到您的 Web 应用程序的 HTML 中
<script src="https://cdn.jsdelivr.net.cn/npm/@elastic/search-application-client@latest"></script>
安装完成后,您可以将客户端导入到您的 Web 应用程序中。 您需要以下信息来初始化客户端
- 您的搜索应用程序的 名称
- 您的搜索应用程序的 URL 端点
- 您的搜索应用程序的 API 密钥
在 Kibana UI 的 Connect 页面上查找此信息。
使用以下导入语句
import SearchApplicationClient from '@elastic/search-application-client';
使用您的部署详细信息配置客户端以开始发出搜索请求。 您可以在 Kibana UI 的 Connect 页面上生成 API 密钥。 转到 Search > Search Applications > <MY_SEARCH_APPLICATION> > Connect。 您将找到以下预先填充的信息来初始化客户端
import Client from '@elastic/search-application-client'
const request = Client(
'my-search-application',
'url-from-connect-page',
'api-key-from-connect-page',
{
// optional configuration
}
)
- 搜索应用程序名称
- url-host
- api-key
配置完成后,您可以使用 客户端 API 向您的搜索应用程序发出搜索请求,如下所示
const results = await request()
.query('star wars')
.search()
或者,如果您使用 CDN,则可以使用以下语句导入客户端
<script>
const Client = window['SearchApplicationClient'];
</script>
使用您的部署详细信息配置客户端以开始发出搜索请求。 您可以在 Kibana UI 的 Connect 页面上生成 API 密钥。 转到 Search > Search Applications > <MY_SEARCH_APPLICATION> > Connect。 您将找到以下预先填充的信息来初始化客户端
<script>
const request = Client(
'my-example-app',
'url-from-connect-page',
'api-key-from-connect-page',
{
// optional configuration
}
)
</script>
- 搜索应用程序名称
- url-host
- api-key
配置完成后,您可以使用 客户端 API 向您的搜索应用程序发出搜索请求,如下所示
<script>
const results = await request()
.query('star wars')
.search()
</script>
搜索应用程序客户端旨在与您创建的任何 搜索模板 一起使用。 您将使用搜索应用程序 API 来创建和管理您的搜索模板。
在使用搜索应用程序 API 管理模板时,我们使用 Kibana Console^ 语法提供 API 示例。
这是一个示例模板
PUT _application/search_application/my-example-app
{
"indices": ["my-example-app"],
"template": {
"script": {
"lang": "mustache",
"source": """
{
"query": {
"bool": {
"must": [
{{#query}}
{
"query_string": {
"query": "{{query}}",
"search_fields": {{#toJson}}search_fields{{/toJson}}
}
}
{{/query}}
]
}
}
}
""",
"params": {
"query": "",
"search_fields": ""
}
}
}
}
这将允许您将所需的任何模板参数添加到模板中,然后在客户端请求中提供这些值。 使用 addParameter
将实际值注入到您的模板参数中。
例如,像这样传入 search_fields
的值
const results = await request()
.query('star wars')
.addParameter('search_fields', ['title', 'description'])
.search()
- 要求模板使用查询参数
我们建议从客户端存储库中提供的 样板模板 开始。 查看此脚本 以了解它的使用方式。 dictionary
参数用于传入 JSON 模式定义,该定义描述了请求对象的结构和验证规则。 此模式非常重要,因为它限制了 Elasticsearch 查询中某些功能的使用。 查看该模式。
本指南中的每个搜索功能都需要此模板中包含的功能。 这些功能需要模板中存在特定参数
- 查询:
query
- 过滤器:
_es_filters
- 分面:
_es_filters
和_es_aggs
- 排序:
_es_sort_fields
- 分页:
from
和size
我们将探索搜索体验所需的所有基本知识。 您将学习如何使用搜索应用程序实现它们,并使用客户端查询它们。
有关可用方法及其参数的信息,请参阅 客户端存储库。
我们简单的模板使用跨所有字段的 query_string
搜索,但这可能不适合您的用例。 您可以更新模板以提供更好的相关性召回率。
在下面的示例中,我们针对我们的模板使用 multi-match
查询,其中 best_fields
和 phrase_prefix
查询针对不同的搜索字段。
PUT _application/search_application/my-example-app
{
"indices": ["example-index"],
"template": {
"script": {
"lang": "mustache",
"source": """
{
"query": {
"bool": {
"must": [
{{#query}}
{
"multi_match" : {
"query": "{{query}}",
"fields": [ "title^4", "plot", "actors", "directors" ]
}
},
{
"multi_match" : {
"query": "{{query}}",
"type": "phrase_prefix",
"fields": [ "title^4", "plot"]
}
},
{{/query}}
],
"filter": {{#toJson}}_es_filters{{/toJson}}
}
},
"aggs": {{#toJson}}_es_aggs{{/toJson}},
"from": {{from}},
"size": {{size}},
"sort": {{#toJson}}_es_sort_fields{{/toJson}}
}
""",
"params": {
"query": "",
"_es_filters": {},
"_es_aggs": {},
"_es_sort_fields": {},
"size": 10,
"from": 0
},
"dictionary": {
// add dictionary restricting
// _es_filters, _es_sort_fields & _es_aggs params
// Use example provided in repo: https://github.com/elastic/search-application-client/blob/main/bin/request_schema.json
}
}
}
}
有关不同类型的查询示例,包括文本搜索、kNN 搜索、ELSER 搜索、带有 RRF 的混合搜索等,请参阅。
用例:我想动态调整搜索字段
如果您需要在查询请求时调整 search_fields
,您可以向模板添加一个新参数(例如:search_fields
),并使用 addParameter
方法向模板提供字段。
用例:我想提高结果,给定与用户的某个接近程度
您可以添加其他模板参数以发送用户的地理坐标。 然后使用 function_score
来提高与用户的某个 geo_distance
匹配的文档。
默认情况下,所有字段都返回在 _source
字段中。 要限制返回的字段,请在模板中指定这些字段。
PUT _application/search_application/my-example-app
{
"indices": ["example-index"],
"template": {
"script": {
"lang": "mustache",
"source": """
{
"query": {
"bool": {
"must": [
{{#query}}
// ...
{{/query}}
],
"filter": {{#toJson}}_es_filters{{/toJson}}
}
},
"_source": {
"includes": ["title", "plot"]
},
"aggs": {{#toJson}}_es_aggs{{/toJson}},
"from": {{from}},
"size": {{size}},
"sort": {{#toJson}}_es_sort_fields{{/toJson}}
}
""",
"params": {
"query": "",
"_es_filters": {},
"_es_aggs": {},
"_es_sort_fields": {},
"size": 10,
"from": 0
},
"dictionary": {
// add dictionary restricting _es_filters and _es_aggs params
// Use the dictionary example provided in repo: https://github.com/elastic/search-application-client/blob/main/bin/request_schema.json
}
}
}
}
用例:我想动态调整结果字段
如果您需要在查询请求时调整返回的字段,您可以向模板添加一个新参数(例如:result_fields
),并使用 addParameter
方法向模板提供字段。
突出显示支持很容易添加到模板中。 使用 突出显示 API,您可以指定要突出显示哪些字段以进行匹配。
在以下示例中,我们将 title
和 plot
指定为突出显示的字段。 与可变且往往更长的 plot
相比,title
通常具有较短的值长度。
我们将标题指定为 fragment_size
为 0
,以便在有突出显示时返回所有文本。 我们将 plot 指定为 fragment_size
为 200
,其中每个突出显示的代码片段最多为 200 个字符长。
PUT _application/search_application/my-example-app
{
"indices": ["example-index"],
"template": {
"script": {
"lang": "mustache",
"source": """
{
"query": {
"bool": {
"must": [
{{#query}}
// ...
{{/query}}
],
"filter": {{#toJson}}_es_filters{{/toJson}}
}
},
"_source": {
"includes": ["title", "plot"]
},
"highlight": {
"fields": {
"title": { "fragment_size": 0 },
"plot": { "fragment_size": 200 }
}
},
"aggs": {{#toJson}}_es_aggs{{/toJson}},
"from": {{from}},
"size": {{size}},
"sort": {{#toJson}}_es_sort_fields{{/toJson}}
}
""",
"params": {
"query": "",
"_es_filters": {},
"_es_aggs": {},
"_es_sort_fields": {},
"size": 10,
"from": 0
},
"dictionary": {
// add dictionary restricting _es_filters and _es_aggs params
// Use the dictionary example provided in repo: https://github.com/elastic/search-application-client/blob/main/bin/request_schema.json
}
}
}
}
如果找到匹配项,这将返回带有突出显示字段的结果。 例如
{
"hits": [
{
"_index": "movies",
"_type": "_doc",
"_id": "1",
"_score": 0.2876821,
"_source": {
"title": "The Great Gatsby",
"plot": "The Great Gatsby is a novel by F. Scott Fitzgerald that follows the story of Jay Gatsby, a wealthy and mysterious man, as he tries to win back the love of his life, Daisy Buchanan."
},
"highlight": {
"title": ["The Great <em>Gatsby</em>"],
"plot": [
"The Great <em>Gatsby</em> is a novel by F. Scott Fitzgerald that follows the story of <em>Jay</em> <em>Gatsby</em>, a wealthy and mysterious man, as he tries to win back the love of his life, Daisy Buchanan."
]
}
}
]
}
在前端显示字段时,您首先需要确定该字段是否具有突出显示。 为了简化此过程,我们提供了一个助手。
import Client, { Highlight } from '@elastic/search-application-client'
// example React component
const ResultsList = ({ hits } ) => {
return hits.map((hit) => (
<div className="result">
<div className="title">{Highlight(hit, "title")}</div>
<div className="description">{Highlight(hit, "plot")}</div>
</div>
))
}
要使用分页,请设置页码和页面大小。默认情况下,页面大小为 10。size
和 from
参数允许您控制响应中返回的页面和命中次数。
我们可以使用客户端的 setSize
和 setFrom
方法来实现这一点。
// page 1
const results = await request()
.setSize(20)
.setFrom(0)
.search()
// page 2
const results = await request()
.setSize(20)
.setFrom(20)
.search()
要使用排序,请指定字段名称和排序顺序,或者 pass _score
以按相关性排序。需要在搜索模板中使用 _es_sort_fields_fields
参数。请参阅我们的示例模板,了解它的使用位置。
默认情况下,结果将按分数排序。如果需要按分数以外的字段排序,请使用 setSort
方法和对象数组。
const results = await request()
.setSort([{ year: 'asc' }, '_score'])
.search()
搜索应用程序客户端还支持过滤器和分面。要使用这些,您需要添加两个参数
_es_filters
_es_aggs
请参阅我们的示例模板,了解它的使用位置。
使用配置为使用过滤器的模板,使用 setFilter
方法向查询添加过滤器。
样板模板模式仅支持 term、range、match、nested、geo_bounding_box 和 geo_distance 过滤器。如果需要使用特定子句,可以更新模板模式。
以下是使用 setFilter
的示例。
// return only "star wars" movies that are rated PG
const results = await request()
.query('star wars')
.setFilter({
term: {
'rated.enum': 'PG',
},
})
.search()
客户端支持配置结果分面的功能。在客户端初始化调用中指定分面。例如,假设我们要为演员、导演和 IMDB 评分添加分面。
const request = Client(
'my-example-app',
'https://d1bd36862ce54c7b903e2aacd4cd7f0a.us-east4.gcp.elastic-cloud.com:443',
'api-key-from-connect-page',
{
facets: {
actors: {
type: 'terms',
field: 'actors.keyword',
disjunctive: true,
},
directors: {
type: 'terms',
field: 'director.keyword',
size: 20,
disjunctive: true,
},
imdbrating: {
type: 'stats',
field: 'imdbrating',
},
},
}
)
- 搜索应用程序名称
- api-host
- api-key
在 Elasticsearch 中,keyword
类型用于需要以其精确、未修改的形式搜索的字段。这意味着这些查询区分大小写。我们对分面使用此类型,因为分面需要基于精确值或术语聚合和过滤数据。
使用 addFacetFilter
方法向查询添加分面。
在以下示例中,我们只想返回电影
- 以哈里森·福特为演员
- 由乔治·卢卡斯或雷德利·斯科特执导
- IMBD 评分大于 7.5
const results = await request()
.addFacetFilter('actors', 'Harrison Ford')
.addFacetFilter('directors', 'George Lucas')
.addFacetFilter('directors', 'Ridley Scott')
.addFacetFilter('imdbrating', {
gte: 7.5,
})
.search()
您可以访问结果中的分面
{
"took": 1,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 2,
"relation": "eq"
},
"max_score": 0,
"hits": [
{
"_index": "imdb_movies",
"_id": "tt0076759",
"_score": 0,
"_source": {
"title": "Star Wars: Episode IV - A New Hope",
"actors": [
"Mark Hamill",
"Harrison Ford",
"Carrie Fisher",
"Peter Cushing"
],
"plot": "Luke Skywalker joins forces with a Jedi Knight, a cocky pilot, a wookiee and two droids to save the universe from the Empire's world-destroying battle-station, while also attempting to rescue Princess Leia from the evil Darth Vader.",
"poster": "https://s3-eu-west-1.amazonaws.com/imdbimages/images/MV5BMTU4NTczODkwM15BMl5BanBnXkFtZTcwMzEyMTIyMw@@._V1_SX300.jpg"
}
},
{
"_index": "imdb_movies",
"_id": "tt0083658",
"_score": 0,
"_source": {
"title": "Blade Runner",
"actors": [
"Harrison Ford",
"Rutger Hauer",
"Sean Young",
"Edward James Olmos"
],
"plot": "Deckard, a blade runner, has to track down and terminate 4 replicants who hijacked a ship in space and have returned to Earth seeking their maker.",
"poster": "https://s3-eu-west-1.amazonaws.com/imdbimages/images/MV5BMTA4MDQxNTk2NDheQTJeQWpwZ15BbWU3MDE2NjIyODk@._V1_SX300.jpg"
}
}
]
},
"aggregations": {},
"facets": [
{
"name": "imdbrating_facet",
"stats": {
"min": 8.300000190734863,
"max": 8.800000190734863,
"avg": 8.550000190734863,
"sum": 17.100000381469727,
"count": 2
}
},
{
"name": "actors_facet",
"entries": [
{
"value": "Harrison Ford",
"count": 2
},
{
"value": "Carrie Fisher",
"count": 1
},
{
"value": "Edward James Olmos",
"count": 1
},
{
"value": "Mark Hamill",
"count": 1
},
{
"value": "Peter Cushing",
"count": 1
},
{
"value": "Rutger Hauer",
"count": 1
},
{
"value": "Sean Young",
"count": 1
}
]
},
{
"name": "directors_facet",
"entries": [
{
"value": "Steven Spielberg",
"count": 3
},
{
"value": "Andrew Davis",
"count": 1
},
{
"value": "George Lucas",
"count": 1
},
{
"value": "Irvin Kershner",
"count": 1
},
{
"value": "Richard Marquand",
"count": 1
},
{
"value": "Ridley Scott",
"count": 1
}
]
}
]
}