如何通过字段值限制 ElasticSearch 结果?

How to limit ElasticSearch results by a field value?

我们有一个系统可以使用映射器附件插件在 ElasticSearch 中为简历文档编制索引。除了索引文档外,我还存储了一些基本信息,比如它是否与申请人或雇员相关、他们的姓名以及他们在系统中分配的 ID。运行的查询在遇到 ES:

时可能看起来像这样
{
  "size" : 100,
  "query" : {
    "query_string" : {
      "query" : "software AND (developer OR engineer)",
       "default_field" : "fileData"
    }
  },
  "_source" : {
    "includes" : [ "applicant.*", "employee.*" ]
  }
}

得到如下结果:

"hits": [100]
    0:  {
      "_index": "careers"
      "_type": "resume"
      "_id": "AVEW8FJcqKzY6y-HB4tr"
      "_score": 0.4530588
      "_source": {
      "applicant": {
        "name": "John Doe"
        "id": 338338
        }
      }
    }...

我想做的是限制结果,这样如果 John Doe 的 ID 为 338338 在系统中有三份不同的简历都匹配查询,我只得到一份匹配,最好是得分最高的一份(虽然那不是那么重要,只要我能找到那个人)。我一直在尝试使用过滤器和聚合的不同选项,但我还没有偶然发现执行此操作的方法。

在返回结果后,我可以在调用 ES 的应用程序中采用多种方法来解决这个问题,但如果我可以在 ES 端完成,那将是更可取的。由于我将查询限制为 100 个结果,我想返回 100 个个人,而不是返回 100 个结果,然后发现其中 25% 的文档与同一个人有关。

您要做的是聚合以获取前 100 条唯一记录,然后进行子聚合以获取 "top_hits"。这是我系统中的一个例子。在我的示例中,我是:

  1. 将结果大小设置为 0 因为我只关心聚合
  2. 将聚合大小设置为 100
  3. 对于每个聚合,获取前 1 个结果

GET index1/type1/_search { "size": 0, "aggs": { "a1": { "terms": { "field": "input.user.name", "size": 100 }, "aggs": { "topHits": { "top_hits": { "size": 1 } } } } } }

使用上面的答案和 IanGabes 的 link,我能够像这样重组我的搜索:

{
    "size": 0,
    "query": {
        "query_string": {
            "query": "software AND (developer OR engineer)",
            "default_field": "fileData"
        }
    },
    "aggregations": {
        "employee": {
            "terms": {
                "field": "employee.id",
                "size": 100
            },
            "aggregations": {
                "score": {
                    "max": {
                        "script": "scores"
                    }
                }
            }
        },
        "applicant": {
            "terms": {
                "field": "applicant.id",
                "size": 100
            },
            "aggregations": {
                "score": {
                    "max": {
                        "script": "scores"
                    }
                }
            }
        }
    }
}

这让我得到了两个桶,一个包含所有申请人 ID 和匹配文档中的最高分数,以及员工的相同分数。该脚本无非是包含'_score'作为内容的分片上的groovy脚本。

有一种更简单的方法可以通过使用 Elasticsearch 的折​​叠功能来完成@ckasek 的目标。

字段折叠,如 Elasticsearch docs 中所述:

Allows to collapse search results based on field values. The collapsing is done by selecting only the top sorted document per collapse key.

基于上面的原始查询示例,您可以这样修改它:

{
  "size" : 100,
  "query" : {
    "query_string" : {
      "query" : "software AND (developer OR engineer)",
       "default_field" : "fileData"
    }
  },
  "collapse": {
    "field": "id",
  },
  "_source" : {
    "includes" : [ "applicant.*", "employee.*" ]
  }
}