介绍 Kibana 中的 Elasticsearch 查询规则用户界面
了解如何使用 Elasticsearch 查询规则用户界面,在 Kibana 中使用可定制的规则集从搜索查询中添加或排除文档,而不影响有机排名。
搜索引擎的工作就是返回相关结果。然而,有些业务需求并不限于此,比如突出销售、优先考虑季节性产品或展示赞助项目,而开发人员不可能总是在搜索查询中做到这一点。
此外,这些用例通常具有时间敏感性,而经历典型的开发阶段(创建代码分支,然后等待新版本发布)是一个耗时的过程。
那么,如果我们只需调用 API,或者在 Kibana 中点击几下就能完成整个过程,那会怎样呢?
查询规则用户界面
Elasticsearch 8.10 引入了查询规则和规则检索器。这些工具旨在根据规则在不影响有机结果排名的情况下将钉入结果注入查询。它们只是以声明式的简单方式在结果之上添加业务逻辑。
查询规则的一些常见用例包括
突出显示促销列表或销售:在顶部显示促销或赞助商品。
根据上下文或地理位置排除:当当地法规不允许显示某些项目时,隐藏这些项目。
优先处理关键结果:确保热门搜索或固定搜索始终排在前面,无论有机搜索排名如何。
要访问界面并与这些工具互动,需要点击 Kibana 侧边菜单,然后转到相关性下的查询规则 :

查询规则菜单弹出后,点击创建第一个规则集:

接下来,您需要为规则集命名。

定义每条规则的表格有三个关键部分:
标准:适用规则必须满足的条件。例如,"当 query_string 字段包含Christmas值时 "或 "当 country 字段为CO 时"。
行动:这是您希望在条件满足时发生的事情。它可以被固定(将文档固定到顶部结果)或排除(隐藏文档)。
元数据:这些字段在查询运行时会随查询一起出现。它们可以包括用户信息(如位置或语言)以及搜索数据(query_string)。这些值是标准用于决定是否应用规则的值。
例如:热门项目
假设我们有一个电子商务网站,上面有不同的商品。在查看这些指标时,我们注意到在游戏机类别中,"DualShock 4 无线控制器 "是销售量最大的商品之一,尤其是当用户搜索关键词 "PS4 "或 "PlayStation 4 "时。因此,我们决定在用户搜索这些关键词时,将该产品放在搜索结果的顶部。
首先,让我们使用批量 API 请求为每个项目的文档建立索引:
POST _bulk
{ "index": { "_index": "products", "_id": "1" } }
{ "id": "1", "name": "PlayStation 4 Slim 1TB", "category": "console", "brand": "Sony", "price": 1200 }
{ "index": { "_index": "products", "_id": "2" } }
{ "id": "2", "name": "DualShock 4 Wireless Controller", "category": "accessory", "brand": "Sony", "price": 250 }
{ "index": { "_index": "products", "_id": "3" } }
{ "id": "3", "name": "PlayStation 4 Camera", "category": "accessory", "brand": "Sony", "price": 200 }
{ "index": { "_index": "products", "_id": "4" } }
{ "id": "4", "name": "PlayStation 4 VR Headset", "category": "accessory", "brand": "Sony", "price": 900 }
{ "index": { "_index": "products", "_id": "5" } }
{ "id": "5", "name": "Charging Station for DualShock 4", "category": "accessory", "brand": "Sony", "price": 80 }如果我们不干预查询,该项目通常会出现在第四位。问题是这样的
GET products/_search
{
"query": {
"match": {
"name": "PlayStation 4"
}
}
}结果如下
{
"took": 1,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 5,
"relation": "eq"
},
"max_score": 0.6973252,
"hits": [
{
"_index": "products",
"_id": "3",
"_score": 0.6973252,
"_source": {
"id": "3",
"name": "PlayStation 4 Camera",
"category": "accessory",
"brand": "Sony",
"price": 200
}
},
{
"_index": "products",
"_id": "1",
"_score": 0.6260078,
"_source": {
"id": "1",
"name": "PlayStation 4 Slim 1TB",
"category": "console",
"brand": "Sony",
"price": 1200
}
},
{
"_index": "products",
"_id": "4",
"_score": 0.6260078,
"_source": {
"id": "4",
"name": "PlayStation 4 VR Headset",
"category": "accessory",
"brand": "Sony",
"price": 900
}
},
{
"_index": "products",
"_id": "2",
"_score": 0.08701137,
"_source": {
"id": "2",
"name": "DualShock 4 Wireless Controller",
"category": "accessory",
"brand": "Sony",
"price": 250
}
},
{
"_index": "products",
"_id": "5",
"_score": 0.07893815,
"_source": {
"id": "5",
"name": "Charging Station for DualShock 4",
"category": "accessory",
"brand": "Sony",
"price": 80
}
}
]
}
}让我们创建一个查询规则来改变这种情况。首先,让我们像这样把它添加到规则集中:

或相应的API 请求:
PUT _query_rules/my-rules
{
"rules": [
{
"rule_id": "rule-1232",
"type": "pinned",
"criteria": [
{
"type": "exact",
"metadata": "query_string",
"values": [
"PS4",
"PlayStation 4"
]
}
],
"actions": {
"docs": [
{
"_index": "products",
"_id": "2"
}
]
}
}
]
}要在查询中使用规则集 ,我们必须使用查询规则类型。这种查询主要由两部分组成:
GET /products/_search
{
"retriever": {
"rule": {
"retriever": {
"standard": {
"query": {
"match": { "name": "PlayStation 4" }
}
}
},
"match_criteria": {
"query_string": "PlayStation 4"
},
"ruleset_ids": ["my-rules"]
}
}
}匹配标准:这些是用于与用户查询进行比较的元数据。在本例中,当 query_string 字段的值为 "PlayStation 4 "时,规则集被激活。
query:实际查询,用于搜索和获取有机结果。
这样,首先运行有机查询,然后 Elasticsearch 应用规则集中的规则:
{
"took": 17,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 5,
"relation": "eq"
},
"max_score": 1.7014122e+38,
"hits": [
{
"_index": "products",
"_id": "2",
"_score": 1.7014122e+38,
"_source": {
"id": "2",
"name": "DualShock 4 Wireless Controller",
"category": "accessory",
"brand": "Sony",
"price": 250
}
},
{
"_index": "products",
"_id": "3",
"_score": 0.6973252,
"_source": {
"id": "3",
"name": "PlayStation 4 Camera",
"category": "accessory",
"brand": "Sony",
"price": 200
}
},
{
"_index": "products",
"_id": "1",
"_score": 0.6260078,
"_source": {
"id": "1",
"name": "PlayStation 4 Slim 1TB",
"category": "console",
"brand": "Sony",
"price": 1200
}
},
{
"_index": "products",
"_id": "4",
"_score": 0.6260078,
"_source": {
"id": "4",
"name": "PlayStation 4 VR Headset",
"category": "accessory",
"brand": "Sony",
"price": 900
}
},
{
"_index": "products",
"_id": "5",
"_score": 0.07893815,
"_source": {
"id": "5",
"name": "Charging Station for DualShock 4",
"category": "accessory",
"brand": "Sony",
"price": 80
}
}
]
}
}示例:基于用户的元数据
查询规则的另一个有趣应用是使用元数据,根据用户或网页的上下文信息显示特定文档。
例如,假设我们想根据用户的忠诚度(用数值表示)来突出显示商品或定制销售。
我们可以直接将这些元数据导入查询,这样当所述值满足特定条件时,规则就会激活。
首先,我们将为一份只有忠诚度高的用户才能看到的文档建立索引:
POST _bulk
{ "index": { "_index": "products", "_id": "6" } }
{ "id": "6", "name": "PlayStation Plus Deluxe Card - 12 months", "category": "membership", "brand": "Sony", "price": 300 }现在,让我们在同一规则集内创建一条新规则,这样当忠诚度_级别等于或高于 80 时,项目就会出现在结果的顶部。

保存规则和规则集。
以下是相应的 REST 请求:
PUT _query_rules/my-rules
{
"rules": [
{
"rule_id": "pin-premiun-user",
"type": "pinned",
"criteria": [
{
"type": "gte",
"metadata": "loyalty_level",
"values": [
80
]
}
],
"actions": {
"docs": [
{
"_index": "products",
"_id": "6"
}
]
}
}
]
}现在,在运行查询时,我们需要在元数据中包含新参数loyalty_level 。如果满足规则中的条件,新文档将出现在结果的顶部。
例如,在发送忠诚度级别为 80 的查询时:
POST /products/_search
{
"retriever": {
"rule": {
"retriever": {
"standard": {
"query": {
"match": {
"name": "PlayStation"
}
}
}
},
"match_criteria": {
"query_string": "PlayStation",
"loyalty_level": 80
},
"ruleset_ids": ["my-rules"]
}
}
}我们将在结果上方看到忠诚度文件:
{
"took": 31,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 4,
"relation": "eq"
},
"max_score": 1.7014122e+38,
"hits": [
{
"_index": "products",
"_id": "6",
"_score": 1.7014122e+38,
"_source": {
"id": "6",
"name": "PlayStation Plus Deluxe Card - 12 months",
"category": "membership",
"brand": "Sony",
"price": 300
}
},
{
"_index": "products",
"_id": "3",
"_score": 0.5054567,
"_source": {
"id": "3",
"name": "PlayStation 4 Camera",
"category": "accessory",
"brand": "Sony",
"price": 200
}
},
{
"_index": "products",
"_id": "1",
"_score": 0.45618832,
"_source": {
"id": "1",
"name": "PlayStation 4 Slim 1TB",
"category": "console",
"brand": "Sony",
"price": 1200
}
},
{
"_index": "products",
"_id": "4",
"_score": 0.45618832,
"_source": {
"id": "4",
"name": "PlayStation 4 VR Headset",
"category": "accessory",
"brand": "Sony",
"price": 900
}
}
]
}
}在下面的例子中,由于忠诚度等级为 70,因此不符合规则,物品不应出现在顶部:
POST /products/_search
{
"retriever": {
"rule": {
"retriever": {
"standard": {
"query": {
"match": {
"name": "PlayStation"
}
}
}
},
"match_criteria": {
"query_string": "PlayStation",
"loyalty_level": 70
},
"ruleset_ids": ["my-rules"]
}
}
}结果如下:
{
"took": 7,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 4,
"relation": "eq"
},
"max_score": 0.5054567,
"hits": [
{
"_index": "products",
"_id": "3",
"_score": 0.5054567,
"_source": {
"id": "3",
"name": "PlayStation 4 Camera",
"category": "accessory",
"brand": "Sony",
"price": 200
}
},
{
"_index": "products",
"_id": "1",
"_score": 0.45618832,
"_source": {
"id": "1",
"name": "PlayStation 4 Slim 1TB",
"category": "console",
"brand": "Sony",
"price": 1200
}
},
{
"_index": "products",
"_id": "4",
"_score": 0.45618832,
"_source": {
"id": "4",
"name": "PlayStation 4 VR Headset",
"category": "accessory",
"brand": "Sony",
"price": 900
}
},
{
"_index": "products",
"_id": "6",
"_score": 0.3817649,
"_source": {
"id": "6",
"name": "PlayStation Plus Deluxe Card - 12 months",
"category": "membership",
"brand": "Sony",
"price": 300
}
}
]
}
}例如:立即排除
假设我们的DualShock 4 无线控制器(ID 2)暂时缺货,无法出售。因此,业务团队决定在此期间将其从搜索结果中删除,而不是手动删除文档或等待某些数据流程启动。
我们将使用与刚才应用于热门项目类似的过程,但这次我们不选择 "已固定",而是选择 "排除"。这条规则就像一个黑名单。将条件改为 "始终",这样每次运行查询时,排除都会起作用。
规则应该是这样的

保存规则和规则集以应用更改。以下是相应的 REST 请求:
PUT _query_rules/my-rules
{
"rules": [
{
"rule_id": "rule-6358",
"type": "pinned",
"criteria": [
{
"type": "always"
}
],
"actions": {
"docs": [
{
"_index": "products",
"_id": "2"
}
]
}
}
]
}现在,当我们再次运行查询时,你会发现结果中不再有该项目,尽管之前的规则是将其固定。这是因为排除结果的优先级高于钉牢结果。
{
"took": 6,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 4,
"relation": "eq"
},
"max_score": 2.205655,
"hits": [
{
"_index": "products",
"_id": "3",
"_score": 2.205655,
"_source": {
"id": "3",
"name": "PlayStation 4 Camera",
"category": "accessory",
"brand": "Sony",
"price": 200
}
},
{
"_index": "products",
"_id": "1",
"_score": 1.9738505,
"_source": {
"id": "1",
"name": "PlayStation 4 Slim 1TB",
"category": "console",
"brand": "Sony",
"price": 1200
}
},
{
"_index": "products",
"_id": "4",
"_score": 1.9738505,
"_source": {
"id": "4",
"name": "PlayStation 4 VR Headset",
"category": "accessory",
"brand": "Sony",
"price": 900
}
},
{
"_index": "products",
"_id": "5",
"_score": 0.69247496,
"_source": {
"id": "5",
"name": "Charging Station for DualShock 4",
"category": "accessory",
"brand": "Sony",
"price": 80
}
}
]
}
}结论
查询规则使调整相关性变得非常容易,无需修改任何代码。新的Kibana UI 允许 在几秒钟内做出这些更改,让您和您的业务团队对搜索结果拥有更多控制权。
除电子商务外,查询规则还能支持许多其他应用场景:在支持门户中突出显示故障排除指南,在知识库中显示关键的内部文档,在新闻网站中宣传突发事件,或过滤掉过期的职位或内容列表。它们甚至可以执行合规规则,如根据用户角色或地区隐藏受限资料。




