Elasticsearch订单条款按得分汇总

drd*_*man 1 sorting search aggregation relevance elasticsearch

我是ElasticSearch的新手。以前,我仅以非常有限的方式仅将其用于Django-Haystack,并且从未直接与ES交流过。

目前,我有一个带有几个文档的ElasticSearch(如果重要的话,为5.x)索引。我使用的是Python + Elasticsearch-dsl + django-elasticsearch-dsl,因此我正在为数据库模型建立索引,但这并不重要。我将尽力使这个问题与图书馆无关。

从概念上讲,我将用户及其帖子存储在同一索引中。用户文档和帖子文档有一个共同点-一个字段user_id

用户看起来像这样:

{
    "_id": 1,
    "_type": "user_document",
    "username": "jdoe",
    "user_id": 1,
    "title": "Test user"
}
Run Code Online (Sandbox Code Playgroud)

帖子是这样的:

{
    "_id": 1,
    "_doc": "post_document",
    "user_id": 1,
    "title": "Hello world!",
    "text": "Lorem ipsum test test test..."
}
Run Code Online (Sandbox Code Playgroud)

我要我的应用程序实现的是一个单输入搜索字段,该字段可以对用户及其帖子进行全文搜索(在现实世界中,有更多的文档“类型”-我在这里只是为了举例而简化) 。我想汇总user_id显示仅匹配的不同用户的列表。

目前,我正在这样查询:

{
    "query": {
        "multi_match": {
            "query": "test",
            "fields": ["username^3", "title^2", "text"]
        }
    },
    "aggs": {
        "user_ids": {"terms": {"field": "user_id"}}
    }
}
Run Code Online (Sandbox Code Playgroud)

然后使用响应aggregations.user_ids.buckets.key获取匹配用户的列表。

但是,该列表似乎只是按文档数量排序(因此,如果用户有一对带有“ test”一词的帖子,它们似乎会赢得名为“ test”的用户的称呼),我想尝试排序。我当前的想法是使用平均(或中间值)文档匹配_score

注意:在实际情况下,不仅有两种文档类型,因此采用快捷方式并仅查询特定的文档是_type行不通的。

我怎样才能做到这一点?我正在阅读“按度量排序”一章,但是那里的想法在我身上有些丢失。我做了几次尝试,但它们基本上是胡说八道。任何人都可以显示一个具体的查询示例(最好是在解释中说明其构造方式),以便我可以从中学习?

这是Gist的示例数据集,上面显示的搜索查询以及我得到的确切结果。我想要的(是test_query_01_results.json)是将user_id1优先于2,并具有2.0794415>(0.78306973 + 0.45315093)/ 2的逻辑。

我觉得我做错了的另一件事是,我根本不使用hits-我只是不需要它们-仅使用汇总user_id值。如果可以的话-是否有办法“禁用”它们并仅返回聚合?

Ric*_*cha 5

使用以下查询

{
"size": 0 ,                    ==> to return no hits
"query": {                     ==> query similar to yours
    "multi_match": {
        "query": "test",
        "fields": ["username^3", "title^2", "text"]
    }
},
"aggs": {
    "user_ids": {
        "terms": {
            "field": "user_id",
            "order": {"avg_score": "desc"}
        },
        "aggs": {
            "avg_score": {
                "avg": {"script": "_score"}
              }
          }
      }
    }
  }
Run Code Online (Sandbox Code Playgroud)