渗透
使用 percolate
查询查找与给定文档匹配的存储查询。此操作与常规搜索相反:您查找的是与文档匹配的查询,而不是查找与查询匹配的文档。percolate
查询常用于警报、通知和反向搜索用例。
在使用 percolate
查询时,请考虑以下关键点:
- 您可以对内联提供的文档进行渗滤,或从索引中获取现有文档进行渗滤。
- 文档和存储的查询必须使用相同的字段名称和类型。
- 您可以将渗滤与过滤和评分结合使用,以构建复杂的匹配系统。
percolate
查询被认为是开销较大的查询,仅当集群设置search.allow_expensive_queries
设置为true
(默认值)时才会运行。如果此设置是false
,percolate
查询将被拒绝。
percolate
查询在各种实时匹配场景中都很有用。一些常见用例包括:
- 电子商务通知:用户可以注册对产品的兴趣,例如“当新的 Apple 笔记本电脑有货时通知我”。当新产品文档被索引时,系统会找到所有具有匹配保存查询的用户并发送警报。
- 职位警报:求职者根据偏好的职位名称或地点保存查询,新的职位发布会与这些查询进行匹配以触发警报。
- 安全和警报系统:根据保存的规则或异常模式对传入的日志或事件数据进行渗滤。
- 新闻过滤:将传入文章与保存的主题配置文件进行匹配,以分类或提供相关内容。
渗滤的工作原理
- 保存的查询存储在特殊的
percolator
字段类型中。 - 文档与所有保存的查询进行比较。
- 每个匹配的查询都将返回其
_id
。 - 如果启用了高亮显示,匹配的文本片段也将返回。
- 如果发送了多个文档,
_percolator_document_slot
将显示匹配的文档。
示例
以下示例演示了如何存储 percolate
查询,并使用不同方法对文档进行测试。
创建一个用于存储保存查询的索引
首先,创建一个索引并使用percolator
字段类型配置其 mappings
以存储保存的查询
PUT /my_percolator_index
{
"mappings": {
"properties": {
"query": {
"type": "percolator"
},
"title": {
"type": "text"
}
}
}
}
在 title
字段中添加匹配“apple”的查询
POST /my_percolator_index/_doc/1
{
"query": {
"match": {
"title": "apple"
}
}
}
在 title
字段中添加匹配“banana”的查询
POST /my_percolator_index/_doc/2
{
"query": {
"match": {
"title": "banana"
}
}
}
渗滤内联文档
对照保存的查询测试内联文档
POST /my_percolator_index/_search
{
"query": {
"percolate": {
"field": "query",
"document": {
"title": "Fresh Apple Harvest"
}
}
}
}
响应提供了存储的 percolate
查询,该查询搜索 title
字段中包含单词“apple”的文档,由 _id
: 1
标识
{
...
"hits": {
"total": {
"value": 1,
"relation": "eq"
},
"max_score": 0.13076457,
"hits": [
{
"_index": "my_percolator_index",
"_id": "1",
"_score": 0.13076457,
"_source": {
"query": {
"match": {
"title": "apple"
}
}
},
"fields": {
"_percolator_document_slot": [
0
]
}
}
]
}
}
渗滤多个文档
要在同一个查询中测试多个文档,请使用以下请求
POST /my_percolator_index/_search
{
"query": {
"percolate": {
"field": "query",
"documents": [
{ "title": "Banana flavoured ice-cream" },
{ "title": "Apple pie recipe" },
{ "title": "Banana bread instructions" },
{ "title": "Cherry tart" }
]
}
}
}
_percolator_document_slot
字段帮助您识别每个(按索引)与每个保存查询匹配的文档
{
...
"hits": {
"total": {
"value": 2,
"relation": "eq"
},
"max_score": 0.54726034,
"hits": [
{
"_index": "my_percolator_index",
"_id": "1",
"_score": 0.54726034,
"_source": {
"query": {
"match": {
"title": "apple"
}
}
},
"fields": {
"_percolator_document_slot": [
1
]
}
},
{
"_index": "my_percolator_index",
"_id": "2",
"_score": 0.31506687,
"_source": {
"query": {
"match": {
"title": "banana"
}
}
},
"fields": {
"_percolator_document_slot": [
0,
2
]
}
}
]
}
}
渗滤现有已索引文档
您可以引用已存储在另一个索引中的现有文档,以检查匹配的 percolate
查询。
为您的文档创建一个单独的索引
PUT /products
{
"mappings": {
"properties": {
"title": {
"type": "text"
}
}
}
}
添加文档
POST /products/_doc/1
{
"title": "Banana Smoothie Special"
}
检查存储的查询是否与已索引文档匹配
POST /my_percolator_index/_search
{
"query": {
"percolate": {
"field": "query",
"index": "products",
"id": "1"
}
}
}
当使用存储的文档时,您必须同时提供 index
和 id
。
返回相应的查询
{
...
"hits": {
"total": {
"value": 1,
"relation": "eq"
},
"max_score": 0.13076457,
"hits": [
{
"_index": "my_percolator_index",
"_id": "2",
"_score": 0.13076457,
"_source": {
"query": {
"match": {
"title": "banana"
}
}
},
"fields": {
"_percolator_document_slot": [
0
]
}
}
]
}
}
批量渗滤(多个文档)
您可以在一个请求中检查多个文档
POST /my_percolator_index/_search
{
"query": {
"percolate": {
"field": "query",
"documents": [
{ "title": "Apple event coming soon" },
{ "title": "Banana farms expand" },
{ "title": "Cherry season starts" }
]
}
}
}
每个匹配项都在 _percolator_document_slot
字段中指示匹配的文档
{
...
"hits": {
"total": {
"value": 2,
"relation": "eq"
},
"max_score": 0.46484798,
"hits": [
{
"_index": "my_percolator_index",
"_id": "2",
"_score": 0.46484798,
"_source": {
"query": {
"match": {
"title": "banana"
}
}
},
"fields": {
"_percolator_document_slot": [
1
]
}
},
{
"_index": "my_percolator_index",
"_id": "1",
"_score": 0.41211313,
"_source": {
"query": {
"match": {
"title": "apple"
}
}
},
"fields": {
"_percolator_document_slot": [
0
]
}
}
]
}
}
使用命名查询的多查询渗滤
您可以在命名查询中渗滤不同的文档
GET /my_percolator_index/_search
{
"query": {
"bool": {
"should": [
{
"percolate": {
"field": "query",
"document": {
"title": "Apple pie recipe"
},
"name": "apple_doc"
}
},
{
"percolate": {
"field": "query",
"document": {
"title": "Banana bread instructions"
},
"name": "banana_doc"
}
}
]
}
}
}
name
参数被附加到 _percolator_document_slot
,以提供匹配的查询
{
...
"hits": {
"total": {
"value": 2,
"relation": "eq"
},
"max_score": 0.13076457,
"hits": [
{
"_index": "my_percolator_index",
"_id": "1",
"_score": 0.13076457,
"_source": {
"query": {
"match": {
"title": "apple"
}
}
},
"fields": {
"_percolator_document_slot_apple_doc": [
0
]
}
},
{
"_index": "my_percolator_index",
"_id": "2",
"_score": 0.13076457,
"_source": {
"query": {
"match": {
"title": "banana"
}
}
},
"fields": {
"_percolator_document_slot_banana_doc": [
0
]
}
}
]
}
}
此方法使您能够为单个文档配置更自定义的查询逻辑。在以下示例中,第一个文档查询 title
字段,第二个文档查询 description
字段。还提供了 boost
参数
GET /my_percolator_index/_search
{
"query": {
"bool": {
"should": [
{
"constant_score": {
"filter": {
"percolate": {
"field": "query",
"document": {
"title": "Apple pie recipe"
},
"name": "apple_doc"
}
},
"boost": 1.0
}
},
{
"constant_score": {
"filter": {
"percolate": {
"field": "query",
"document": {
"description": "Banana bread with honey"
},
"name": "banana_doc"
}
},
"boost": 3.0
}
}
]
}
}
}
批量渗滤与命名渗滤的比较
批量渗滤(使用 documents
)和命名渗滤(使用带 name
的 bool
)都可以用于渗滤多个文档,但它们在结果的标签、解释和控制方式上有所不同。它们提供功能相似的结果,但存在重要的结构差异,如下表所述。
功能 | 批量(documents ) | 命名(bool + percolate + name ) |
---|---|---|
输入格式 | 一个渗滤子句,文档数组 | 多个渗滤子句,每个文档一个 |
每文档可追溯性 | 按槽位索引 (0, 1, …) | 按名称(apple_doc , banana_doc ) |
匹配槽位的响应字段 | _percolator_document_slot: [0] | _percolator_document_slot_ |
高亮前缀 | 0_title , 1_title | apple_doc_title , banana_doc_title |
每文档自定义控制 | 不支持 | 可以自定义每个子句 |
支持提升和过滤 | 否 | 是(每个子句) |
性能 | 最适合大型批量 | 子句较多时略慢 |
用例 | 批量匹配作业,大型事件流 | 每文档跟踪、测试、自定义控制 |
高亮显示匹配项
percolate
查询处理高亮显示的方式与常规查询不同
- 在常规查询中,文档存储在索引中,搜索查询用于高亮显示匹配的词项。
- 在
percolate
查询中,角色是反向的:保存的查询(在渗滤器索引中)用于高亮显示文档。
这意味着 document
或 documents
中提供的文档是高亮显示的目标,并且 percolate
查询决定了要高亮的区域。
高亮显示单个文档
此示例使用之前在 my_percolator_index
中定义的搜索。使用以下请求高亮显示 title
字段中的匹配项:
POST /my_percolator_index/_search
{
"query": {
"percolate": {
"field": "query",
"document": {
"title": "Apple banana smoothie"
}
}
},
"highlight": {
"fields": {
"title": {}
}
}
}
匹配项根据匹配的查询进行高亮显示
{
...
"hits": {
"total": {
"value": 2,
"relation": "eq"
},
"max_score": 0.13076457,
"hits": [
{
"_index": "my_percolator_index",
"_id": "1",
"_score": 0.13076457,
"_source": {
"query": {
"match": {
"title": "apple"
}
}
},
"fields": {
"_percolator_document_slot": [
0
]
},
"highlight": {
"title": [
"<em>Apple</em> banana smoothie"
]
}
},
{
"_index": "my_percolator_index",
"_id": "2",
"_score": 0.13076457,
"_source": {
"query": {
"match": {
"title": "banana"
}
}
},
"fields": {
"_percolator_document_slot": [
0
]
},
"highlight": {
"title": [
"Apple <em>banana</em> smoothie"
]
}
}
]
}
}
高亮显示多个文档
当使用 documents
数组渗滤多个文档时,每个文档都会被分配一个槽位索引。高亮键然后采用以下形式,其中 <slot>
是文档在您的 documents
数组中的索引:
"<slot>_<fieldname>": [ ... ]
使用以下命令渗滤两个文档并高亮显示:
POST /my_percolator_index/_search
{
"query": {
"percolate": {
"field": "query",
"documents": [
{ "title": "Apple pie recipe" },
{ "title": "Banana smoothie ideas" }
]
}
},
"highlight": {
"fields": {
"title": {}
}
}
}
响应包含以文档槽位为前缀的高亮字段,例如 0_title
和 1_title
{
...
"hits": {
"total": {
"value": 2,
"relation": "eq"
},
"max_score": 0.31506687,
"hits": [
{
"_index": "my_percolator_index",
"_id": "1",
"_score": 0.31506687,
"_source": {
"query": {
"match": {
"title": "apple"
}
}
},
"fields": {
"_percolator_document_slot": [
0
]
},
"highlight": {
"0_title": [
"<em>Apple</em> pie recipe"
]
}
},
{
"_index": "my_percolator_index",
"_id": "2",
"_score": 0.31506687,
"_source": {
"query": {
"match": {
"title": "banana"
}
}
},
"fields": {
"_percolator_document_slot": [
1
]
},
"highlight": {
"1_title": [
"<em>Banana</em> smoothie ideas"
]
}
}
]
}
}
参数
percolate
查询支持以下参数。
参数 | 必需/可选 | 描述 |
---|---|---|
field | 必需 | 包含存储的 percolate 查询的字段。 |
document | 可选 | 一个用于与保存查询匹配的单个内联文档。 |
documents | 可选 | 一个用于与保存查询匹配的多个内联文档数组。 |
index | 可选 | 包含您要匹配的文档的索引。 |
id | 可选 | 要从索引中获取的文档 ID。 |
路由 | 可选 | 获取文档时要使用的路由值。 |
preference | 可选 | 获取文档时分片路由的偏好设置。 |
名称 | 可选 | 分配给 percolate 子句的名称。在使用 bool 查询中的多个 percolate 子句时很有用。 |