Elasticsearch function_score 查询嵌套数组

问题描述 投票:0回答:1

我正在尝试使用 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 的最高匹配技能(也许是一些内部排序?)。

我尝试了很多不同的查询,但似乎没有一个能按照我需要的方式工作。

如有任何帮助,我们将不胜感激。我也对不同的方法持开放态度,也许有人知道如何以不同的方式实现这一点,或者知道一些有关最佳实践的文档,到目前为止我什么也没发现:/

elasticsearch
1个回答
0
投票

尝试这样的查询

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

行仅过滤最高级别的总和名称
© www.soinside.com 2019 - 2024. All rights reserved.