我正在尝试使用 field_value_factor 查询创建一个查询,以根据某些(匹配的)嵌套数组元素的值来增加文档的分数。
它应该根据匹配查询过滤嵌套数组元素,然后为每个匹配的元素运行 field_value_factor 函数。
这是我到目前为止所拥有的:
索引映射:
{
"mappings": {
"properties": {
"name": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword"
}
}
},
"skills": {
"type": "nested",
"properties": {
"level": {
"type": "short"
},
"id": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword"
}
}
}
}
}
}
}
}
一些文件:
[{
"name": "Alice",
"skills": [ { "id": "aws ecs", "level": 1 },
{ "id": "aws vpc", "level": 2 }]
},{
"name": "Bob",
"skills": [ { "id": "aws ecs", "level": 3 },
{ "id": "aws vpc", "level": 4 }]
},{
"name": "Elli",
"skills": [ { "id": "aws ecs", "level": 7 },
{ "id": "aws vpc", "level": 60},
{ "id": "aws ecr", "level": 1 },
{ "id": "java", "level": 100 }]
}]
现在,假设我们想要找到 AWS 技能总计最高的人。应该是 Elly,因为如果我们搜索“aws”,他们总共有 (7+60+1) 综合经验。
我对此的疑问是:
{
"query": {
"nested": {
"path": "skills",
"query": {
"function_score": {
"query": {
"match_all": {}
},
"functions": [
{
"field_value_factor": {
"field": "skills.level",
"factor": 1,
"missing": 0.1
},
"filter": {
"match": {
"skills.id": "aws"
}
}
}
]
}
}
}
},
"explain": true
}
我将 function_score 包装在嵌套查询中,以针对所有人员的技能运行它(我认为是这样)。然后我对所有匹配“aws”的技能运行 field_value_factor 函数(我认为)。
查询的结果乍一看还不错,Elly 是第一个结果。但是当我查看查询解释时,我可以看到 function_score 查询仅返回 60 分,但我期望分数是 Elly 的所有匹配“aws”技能的总和(7+60+1) =68.
field_value_factor 函数似乎只针对具有最高值的技能运行。首先,我认为这可能与嵌套有关,并且在函数执行时,过滤器的结果是所有匹配技能的扁平数组,并且该函数仅采用第一个(根据文档),但在使用之后Elly 的技能值我可以确认该函数始终采用 Elly 的最高匹配技能(也许是一些内部排序?)。
我尝试了很多不同的查询,但似乎没有一个能按照我需要的方式工作。
如有任何帮助,我们将不胜感激。我也对不同的方法持开放态度,也许有人知道如何以不同的方式实现这一点,或者知道一些有关最佳实践的文档,到目前为止我什么也没发现:/
尝试这样的查询
GET /skills/_search?filter_path=aggregations
{
"aggs": {
"by_name": {
"terms": {
"field": "name.keyword"
},
"aggs": {
"inside_skills": {
"nested": {
"path": "skills"
},
"aggs": {
"filter_out": {
"filter": {
"match_phrase_prefix": {
"skills.id": {
"query": "aws*"
}
}
},
"aggs": {
"level_sum": {
"sum": {
"field": "skills.level"
}
}
}
}
}
},
"sort_by_level_sum": {
"bucket_sort": {
"sort": [
{
"inside_skills>filter_out>level_sum": {
"order": "desc"
}
}
]
}
}
}
}
}
}
回应
{
"aggregations" : {
"by_name" : {
"doc_count_error_upper_bound" : 0,
"sum_other_doc_count" : 0,
"buckets" : [
{
"key" : "Elli",
"doc_count" : 1,
"inside_skills" : {
"doc_count" : 4,
"filter_out" : {
"doc_count" : 3,
"level_sum" : {
"value" : 68.0
}
}
}
},
{
"key" : "Bob",
"doc_count" : 1,
"inside_skills" : {
"doc_count" : 2,
"filter_out" : {
"doc_count" : 2,
"level_sum" : {
"value" : 7.0
}
}
}
},
{
"key" : "Alice",
"doc_count" : 1,
"inside_skills" : {
"doc_count" : 2,
"filter_out" : {
"doc_count" : 2,
"level_sum" : {
"value" : 3.0
}
}
}
}
]
}
}
}
您可以通过
"size": 1
中的
bucket_sort
行仅过滤最高级别的总和名称