2017-05-11 17 views
0

私はElasticSearchを初めて利用しています。これまで私はDjango-Haystackのみを非常に限られた方法で使用してきましたが、ESに直接話をしたことはありません。弾性検索順序の用語集スコア

現在、ElasticSearch(この場合は5.x)のインデックスといくつかのドキュメントがあります。私はPython + elasticsearch-dsl + django-elasticsearch-dslを使用していますので、データベースモデルのインデックスを作成していますが、それは問題ではありません。私はこの質問を図書館にとらわれないままにしようとします。

概念的には、ユーザーとその投稿をすべて同じインデックスに保存しています。ユーザ用と投稿用のドキュメントには共通のものが1つあります。フィールドは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を使用します。

しかし、そのリストはドキュメント数によって単純に並べられているようです(つまり、ユーザーが "test"という単語を含む投稿を持っている場合、 "test"という名前のユーザーに勝つようです)。注文する。私の現在のアイデアは、平均(または中央値)の文書一致_scoreを使用することです。

注:実際の状況では、2つ以上のドキュメントタイプが存在するため、特定の_typeのショートカットを使用してクエリを実行することはできません。

どうすればいいですか?私は"Sorting by a Metric"の章を読んでいますが、そこにあるアイデアは私にはいくらか失われています。私はいくつかの試みを行いましたが、基本的にナンセンスでした。誰も具体的なクエリの例を表示してください(非常に好ましくは、それがどのように構築されたかを説明してください)ので、私はそれから学ぶことができますか?

ここにはGist with an example datasetと、上記の検索クエリと、私が得た正確な結果があります。私は(test_query_01_results.jsonに)したいことは、私は私が間違ってやってる感じもう一つは、そのIドン」です2.0794415>(0.78306973 + 0.45315093)/ 2.

というロジックで、2の上にuser_id 1を優先されていることです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

私は、集計をソートするための解決策を見つけたと思います。サブ集計を作成しなければならなかったので、すべてが機能しました。私は間違っていました。_scoreがないときに"order": {"_score: "desc"}などのナンセンスを使用しようとしていたと誤解されていました(これは文書の集合であり、文書ではないのでスコアはありません)。これにより

{ 
    "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を(私は使用しないことを)持っていることについて質問がまだ保持しています。

関連する問題