2017-05-11 78 views
0

我是ElasticSearch的新手。以前,我只用Django-Haystack以非常有限的方式使用它,并且从未直接与ES交谈过。Elasticsearch订单条款按分数汇总

目前,我有一个ElasticSearch(5.x如果这很重要)索引与几个文件。我正在使用Python + elasticsearch-dsl + django-elasticsearch-dsl,因此我正在对数据库模型建立索引,但它并不重要。我会试着离开这个问题库不可知论。

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

用户是这样的:

{ 
    "_id": 1, 
    "_type": "user_document", 
    "username": "jdoe", 
    "user_id": 1, 
    "title": "Test user" 
} 

和岗位是这样的:

{ 
    "_id": 1, 
    "_doc": "post_document", 
    "user_id": 1, 
    "title": "Hello world!", 
    "text": "Lorem ipsum test test test..." 
} 

我想我的应用程序来实现是一个单输入搜索字段,在做全文搜索用户和他们的帖子(在现实世界中有更多的文档“类型” - 我简化了这里的东西,仅仅是为了举例)。我想要汇总user_id以显示已匹配的不同用户的列表。

目前,我正在做这样的查询:

{ 
    "query": { 
     "multi_match": { 
      "query": "test", 
      "fields": ["username^3", "title^2", "text"] 
     } 
    }, 
    "aggs": { 
     "user_ids": {"terms": {"field": "user_id"}} 
    } 
} 

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

但是,该列表似乎只是按文档计数排序(因此,如果用户有一对文字“测试”他们似乎赢得了名为“测试”的用户),我想试验排序。我目前的想法是使用平均(或中值)文件匹配_score

注意:在实际情况下,不仅仅是两种文档类型,因此在特定的_type上采取快捷方式和查询将不起作用。

我该怎么做?我正在阅读"Sorting by a Metric"一章,但那里的想法对我来说有点失落。我做了一些尝试,但他们基本上是无稽之谈。任何人都可以展示一个具体的查询例子(非常好,解释它是如何构建的),所以我可以从中学习?

这里是Gist with an example dataset,上面显示的搜索查询,以及我得到的确切结果。我想(在test_query_01_results.json)是有user_id 1比2被优先考虑,与逻辑2.0794415>(0.78306973 + 0.45315093)/ 2

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

回答

3

使用下面的查询

{ 
"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"} 
       } 
      } 
     } 
    } 
    } 
+0

感谢。这节省了我的时间。 – Arafath

0

我想我找到了排序聚合的解决方案。我不得不创建一个子聚合,然后这一切工作。我错了,试图使用"order": {"_score: "desc"}和类似的废话,当那里没有任何_score(这是一个文件的集合,而不是一个文件,所以没有得分)。

{ 
    "query": { 
     "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"} 
       } 
      } 
     } 
    } 
} 

有了这个我aggregations看起来只是酷似我想:

... 
"aggregations": { 
    "user_ids": { 
     "buckets": [ 
      { 
       "avg_score": {"value": 2.079441547393799}, 
       "doc_count": 1, 
       "key": 1 
      }, 
      { 
       "avg_score": {"value": 0.618110328912735}, 
       "doc_count": 2, 
       "key": 2 
      } 
     ], 
     "doc_count_error_upper_bound": 0, 
     "sum_other_doc_count": 0 
    } 
}, 
... 

然而,关于有hits的问题(我不使用)仍然成立。