elasticsearch - 如何在 Elasticsearch 中使用无痛脚本获取数组字段的匹配字段值?
问题描述
我正在使用 Elasticsearch 7.6
我在餐厅索引中有如下文件:
"name" : "ABC restaurant",
"menu" : [
{
"name" : "chicken",
"count" : 23
},
{
"name" : "rice",
"count" : 10 }
]
计数是指收到的订单数。
当客户在网站中按菜单名称搜索时,我想给几家餐厅中菜单数量多的餐厅打高分,并将其展示在搜索结果的顶部。
为此,似乎有必要知道无痛脚本中每个文档中的匹配菜单。
我想知道这是可能的。如果是这样,我该怎么做?
更新感谢您的回答@jaspreet chahal
我做了这样的索引:
PUT restaurant
{
"mappings": {
"properties": {
"name": {
"type": "text"
},
"menu":{
"type": "nested",
"properties": {
"name": {"type": "text"},
"count": {"type": "integer"}
}
}
}
}
}
POST /restaurant/_doc/1
{
"name": "ABC Restaurant",
"menu": [
{"name": "chicken", "count": 3},
{"name": "cake", "count": 5}
]
}
POST /restaurant/_doc/2
{
"name": "TEST Restaurant",
"menu": [
{"name": "chicken", "count": 10},
{"name": "cake", "count": 7},
{"name": "rice", "count": 2}
]
}
POST /restaurant/_doc/3
{
"name": "Good Restaurant",
"menu": [
{"name": "chicken", "count": 20},
{"name": "cake", "count": 13},
{"name": "rice", "count": 5}
]
}
我要做的是在使用多重匹配时根据匹配的菜单计数获得总分,如下所示:
GET restaurant/_search
{
"query": {
"bool": {
"must": [
{
"function_score": {
"query": {
"bool": {
"must": [
{
"multi_match": {
"query": "chicken",
"type": "cross_fields",
"fields": [
"menu.name",
"name"
],
"operator": "and"
}
}
]
}
},
"boost_mode": "replace",
"functions": [
{
"field_value_factor": {
"field": "menu.count",
"missing": 0
}
}
]
}
}
]
}
}
}
但是上面的查询没有得到任何结果。
为了使它工作,我在菜单映射中添加了“include_in_root:True”。但是在这种情况下,我无法获得正确的分数..(似乎无论搜索词如何,都获得了菜单计数的最低分数)
请问如何按照我的预期进行这项工作?谢谢 !
再次更新。
我在您的查询中添加了多重匹配
GET restaurant/_search
{
"query": {
"bool": {
"should": [
{
"multi_match": {
"query": "Good Restaurant chicken",
"type": "cross_fields",
"fields": [
"menu.name",
"name"
]
}
},
{
"nested": {
"path": "menu",
"query": {
"function_score": {
"query": {
"bool": {
"should": [
{
"match": {
"menu.name": {
"query": "Good Restaurant chicken",
"operator": "or"
}
}
}
]
}
},
"boost_mode": "replace",
"functions": [
{
"field_value_factor": {
"field": "menu.count",
"missing": 0
}
}
]
}
}
}
}
]
}
}
}
它得到了所有的结果!但是分数受到多匹配查询的影响。
这是查询的结果:
"took" : 1,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 3,
"relation" : "eq"
},
"max_score" : 21.11436,
"hits" : [
{
"_index" : "restaurant",
"_type" : "_doc",
"_id" : "3",
"_score" : 21.11436,
"_source" : {
"name" : "Good Restaurant",
"menu" : [
{
"name" : "chicken",
"count" : 20
},
{
"name" : "cake",
"count" : 13
},
{
"name" : "rice",
"count" : 5
}
]
}
},
{
"_index" : "restaurant",
"_type" : "_doc",
"_id" : "2",
"_score" : 10.133532,
"_source" : {
"name" : "TEST Restaurant",
"menu" : [
{
"name" : "chicken",
"count" : 10
},
{
"name" : "cake",
"count" : 7
},
{
"name" : "rice",
"count" : 2
}
]
}
},
{
"_index" : "restaurant",
"_type" : "_doc",
"_id" : "1",
"_score" : 3.1335313,
"_source" : {
"name" : "ABC Restaurant",
"menu" : [
{
"name" : "chicken",
"count" : 3
},
{
"name" : "cake",
"count" : 5
}
]
}
}
]
}
}
非常感谢您的回答 :)
解决方案
您可以使用function_score根据计数值为嵌套文档提供更高的分数。
询问:
{
"query": {
"nested": {
"path": "menu",
"query": {
"function_score": {
"score_mode": "sum",
"boost_mode": "replace",
"query": {
"match": {
"menu.name": "chicken"
}
},
"functions": [
{
"field_value_factor": {
"field": "menu.count"
}
}
]
}
}
}
}
}
结果:
"hits" : [
{
"_index" : "index63",
"_type" : "_doc",
"_id" : "tA8IPHIBzLrvZDnz-ghE",
"_score" : 23.0,
"_source" : {
"name" : "ABC restaurant",
"menu" : [
{
"name" : "chicken",
"count" : 23
},
{
"name" : "rice",
"count" : 10
}
]
}
},
{
"_index" : "index63",
"_type" : "_doc",
"_id" : "tQ8JPHIBzLrvZDnz-AiA",
"_score" : 20.0,
"_source" : {
"name" : "XYZ restaurant",
"menu" : [
{
"name" : "chicken",
"count" : 20
},
{
"name" : "rice",
"count" : 8
}
]
}
}
]
Edit1: 对于需要使用嵌套查询的嵌套字段,您不能直接在这些字段上运行搜索。
{
"query": {
"bool": {
"should": [
{
"match": {
"name": {
"operator": "and",
"query": "chicken"
}
}
},
{
"nested": {
"path": "menu",
"query": {
"function_score": {
"query": {
"bool": {
"must": [
{
"match": {
"menu.name": {
"query": "chicken",
"operator": "and"
}
}
}
]
}
},
"boost_mode": "replace",
"functions": [
{
"field_value_factor": {
"field": "menu.count",
"missing": 0
}
}
]
}
}
}
}
]
}
}
}
Edit2:要仅考虑来自嵌套查询的分数,您可以给它更高的提升,以便与您的嵌套分数匹配的文档得分更高。如果您不希望您的多重匹配有任何分数。您可以将它放在 constant_score 中,提升为 0,与此匹配的文档将获得 0 分
{
"query": {
"bool": {
"should": [
{
"constant_score": {
"filter": {
"multi_match": {
"query": "Good Restaurant chicken",
"type": "cross_fields",
"fields": [
"name"
]
}
},
"boost": 0
}
},
{
"nested": {
"path": "menu",
"query": {
"function_score": {
"query": {
"bool": {
"should": [
{
"match": {
"menu.name": {
"query": "Good Restaurant chicken",
"operator": "or"
}
}
}
]
}
},
"boost_mode": "replace",
"functions": [
{
"field_value_factor": {
"field": "menu.count",
"missing": 0
}
}
]
}
}
}
}
]
}
}
}
推荐阅读
- php - 使用 dart 对 php 的 Http 发布请求
- python - 如何使用opencv检测手指数量并添加两位数?
- node.js - 如何使用 Heroku 请求 mongodb atlas 数据库
- javascript - 在 Firestore 云文档中动态更新对象和键
- javascript - Bootstrap Vue:如何使进度条随着时间的推移平滑填充
- python - 使用 scipy.optimize 进行曲线拟合时出现 numpy 数组的问题
- android - Google play:此版本不符合 Google play 64 位要求
- python - KivyMD UI 和动画在 Android 上运行缓慢且滞后
- java - PDF 部分下载,状态为 200 并在 ZUUL 网关中显示 SocketException: Connection reset
- c# - Unity 2D 中的自上而下拍摄无法如我所愿