2016-12-06 14 views
9

私は複数の面で同等のデータを検索しようとしています。Elasticsearchで重複を見つける

{ 
    "took" : 5, 
    "timed_out" : false, 
    "_shards" : { 
    "total" : 1, 
    "successful" : 1, 
    "failed" : 0 
    }, 
    "hits" : { 
    "total" : 27524067, 
    "max_score" : 0.0, 
    "hits" : [ ] 
    }, 
    "aggregations" : { 
    "duplicateFIELD1" : { 
     "doc_count_error_upper_bound" : 0, 
     "sum_other_doc_count" : 27524027, 
     "buckets" : [ 
     { 
      "key" : <valueFromField1>, 
      "doc_count" : 4, 
      "duplicateFIELD2" : { 
      "doc_count_error_upper_bound" : 0, 
      "sum_other_doc_count" : 0, 
      "buckets" : [ 
       { 
       "key" : <valueFromField2>, 
       "doc_count" : 2, 
       "duplicateFIELD3" : { 
        "doc_count_error_upper_bound" : 0, 
        "sum_other_doc_count" : 0, 
        "buckets" : [ 
        { 
         "key" : <valueFromField3>, 
         "doc_count" : 2, 
         "duplicateFIELD4" : { 
         "doc_count_error_upper_bound" : 0, 
         "sum_other_doc_count" : 0, 
         "buckets" : [ ] 
         } 
        } 
        ] 
       } 
       }, 
       { 
       "key" : <valueFromField2>, 
       "doc_count" : 2, 
       "duplicateFIELD3" : { 
        "doc_count_error_upper_bound" : 0, 
        "sum_other_doc_count" : 0, 
        "buckets" : [ 
        { 
         "key" : <valueFromField3>, 
         "doc_count" : 2, 
         "duplicateFIELD4" : { 
         "doc_count_error_upper_bound" : 0, 
         "sum_other_doc_count" : 0, 
         "buckets" : [ ] 
         } 
        } 
        ] 
       } 
       } 
      ] 
      } 
     }, 
     { 
      "key" : <valueFromField1>, 
      "doc_count" : 4, 
      "duplicateFIELD2" : { 
      "doc_count_error_upper_bound" : 0, 
      "sum_other_doc_count" : 0, 
      "buckets" : [ 
       { 
       "key" : <valueFromField2>, 
       "doc_count" : 2, 
       "duplicateFIELD3" : { 
        "doc_count_error_upper_bound" : 0, 
        "sum_other_doc_count" : 0, 
        "buckets" : [ 
        { 
         "key" : <valueFromField3>, 
         "doc_count" : 2, 
         "duplicateFIELD4" : { 
         "doc_count_error_upper_bound" : 0, 
         "sum_other_doc_count" : 0, 
         "buckets" : [ ] 
         } 
        } 
        ] 
       } 
       }, 
       { 
       "key" : <valueFromField2>, 
       "doc_count" : 2, 
       "duplicateFIELD3" : { 
        "doc_count_error_upper_bound" : 0, 
        "sum_other_doc_count" : 0, 
        "buckets" : [ 
        { 
         "key" : <valueFromField3>, 
         "doc_count" : 2, 
         "duplicateFIELD4" : { 
         "doc_count_error_upper_bound" : 0, 
         "sum_other_doc_count" : 0, 
         "buckets" : [ ] 
         } 
        } 
        ] 
       } 
       } 
      ] 
      } 
     }, 
     ... 

私は」:これは重複が次のようになり何かを発見しているとき、私が得る結果としてある程度働く

{ 
    "size": 0, 
    "aggs": { 
    "duplicateFIELD1": { 
     "terms": { 
     "field": "FIELD1", 
     "min_doc_count": 2 }, 
     "aggs": { 
     "duplicateFIELD2": { 
      "terms": { 
      "field": "FIELD2", 
      "min_doc_count": 2 }, 
      "aggs": { 
      "duplicateFIELD3": { 
       "terms": { 
       "field": "FIELD3", 
       "min_doc_count": 2 }, 
       "aggs": { 
       "duplicateFIELD4": { 
        "terms": { 
        "field": "FIELD4", 
        "min_doc_count": 2 }, 
        "aggs": { 
        "duplicate_documents": { 
         "top_hits": {} } } } } } } } } } } } 

:私は現在、これは集計をネストする複雑なクエリを使用してくださいむしろ似ている出力の一部をスキップします。

この複雑な深くネストされたデータ構造をスキャンして、これらのネストされたバケットすべてにドキュメントが保存されていないことがわかりました。しかし、これはかなり面倒なようです。私はこれを行うためのより良い(より簡単な)方法かもしれないと思う。

また、4つ以上のフィールドをチェックしたい場合、このネストされた構造が成長し、成長し、成長するでしょう。だから、うまくスケールされていないので、私はこれを避けたい。

解決策を改善して、重複するすべてのドキュメントの簡単なリストを取得できますか? (多分、お互いに重複しているものが何らかの形でグループ化されているかもしれません)、または私がここで説明した欠点を持たない完全に異なるアプローチ(集約なしなど)がありますか?

編集:私はES hereのスクリプト機能を使用してアプローチを見つけましたが、私のバージョンのESではこれはエラーメッセージを返します。おそらく誰かが私にES 5.0でそれをする方法を指摘することができますか?今までの私の試練はうまくいかなかった。

EDIT:

{ 
    "size": 0, 
    "aggs": { 
    "duplicateFOO": { 
     "terms": { 
     "script": { 
      "lang": "painless", 
      "inline": "doc['FIELD1'].value + doc['FIELD2'].value + doc['FIELD3'].value + doc['FIELD4'].value" 
     },     
     "min_doc_count": 2 
     }       
    }       
    } 
} 

これは、データと結果の非常に少量のために働くようだ:私は(言語「無痛」)近代的な方法を使用しています私のアプローチのためのスクリプトを使用する方法を発見しました現実的な量のデータのエラー(circuit_breaking_exception[request] Data too large, data for [<reused_arrays>] would be larger than limit of [6348236390/5.9gb])。どのように私はこれを修正することができますか? ESのいくつかの設定を調整して、より大きな内部バッファーなどを使用するようにしますか?


一般的な方法で入れ子を避ける私の状況に適切な解決策はないようです。

私の4つのフィールドのうち3つは、非常に限られた値の範囲を持っています。最初のものは1または2のみ、2番目のものは1,2または3、3番目のものは1,2,3または4とすることができます。これらは24個の組み合わせであるため、アグリゲーションを適用する前に設定したデータは、の1つ、(残りの4番目のフィールド)です。私はすべてのアクションを24回適用する必要があります(上記の3つの限定フィールドの組み合わせごとに1回)。しかし、これは完全なデータセットを一度に処理するよりも実行可能です。

クエリ(すなわち24個のクエリのいずれか。)私は今、このような何かを見て送信:もちろん、このため

{ 
    "size": 0, 
    "query": { 
    "bool": { 
     "must": [ 
     { "match": { "FIELD1": 2 } }, 
     { "match": { "FIELD2": 3 } }, 
     { "match": { "FIELD3": 4 } } ] } }, 
    "aggs": { 
    "duplicateFIELD4": { 
     "terms": { 
     "field": "FIELD4", 
     "min_doc_count": 2 } } } } 

結果はもはやネストされていません。しかし、複数のフィールドがより大きな範囲の任意の値を保持している場合、これは実行できません。

また、の場合、のネストが行われなければならない場合、最も制限された値の範囲(例えば、"1または2"のような2つの値)が最も内側になり、最大値の範囲が最も外側になるはずです。これによりパフォーマンスが大幅に向上します(ただし、私の場合はまだ十分ではありません)。それが間違っていると、使用できないクエリ(数時間以内に応答がなく、最終的にはサーバー側でメモリ不足になる)が発生する可能性があります。

私は、適切に集約することが私のような問題を解決する鍵であると考えています。フラットバケットリスト(私の質問に記載)を持つスクリプトを使用するアプローチは、どのような方法でもタスクを配布することができないため、サーバに過負荷をかけることになります。ダブルがまったく見つからない場合は、各ドキュメントのバケットをメモリ内に保持する必要があります(その中にドキュメントが1つだけあります)。ほんの数の倍数が見つかったとしても、これは大きなデータセットでは実行できません。他に何もできない場合は、データセットを人為的にグループに分割する必要があります。 E.関連するフィールドからハッシュを構築し、最後の4ビットを使用して16個のグループの上に文書を置くことによって、16個のサブデータセットを作成することができる。各グループは別々に処理することができます。ダブルスはこの技法を使用して1つのグループに分類されます。

しかし、これらの一般的な考え方とは無関係に、ES APIは、集計の結果を改ページする手段を提供する必要があります。そのような選択肢がないことは残念です(まだ)。コピーフィールドを使用しているLogstashシナリオに働くかもしれない

+0

私の意見では、あなたが探しているフィールドの組み合わせが含まれている必要があります(もちろん、これは新しいインデックスにデータを再インデックスすることを意味します)ドキュメントに新しいフィールドを作成することです。次に、検索時にその単一のフィールドに集約することができます。 –

+0

異なるフィールドを連結している場合、複数のフィールドのマージが他のフィールドの組み合わせのマージと同じでないように、複数のフィールドの間にセパレータを追加することが常にベストです。(例: 'test' + 'ing' = 'testing' => 'test' + '#' + 'ing' <> 'testing') – rvheddeg

答えて

0

アイデア:

コピーすべて別々のフィールドに組み合わせて、それらをCONCAT:新しいフィールドを超える

mutate { 
    add_field => { 
    "new_field" => "%{oldfield1} %{oldfield2}" 
    } 
} 

集計。

はこちらをご覧:https://www.elastic.co/guide/en/logstash/current/plugins-filters-mutate.html

add_fieldが配列(あなたはドキュメントを見れば他の人が何を)サポートしている場合、私は知りません。そうでない場合は、いくつかの新しいフィールドを追加し、1つのフィールドだけを持つようにマージを使用することができます。

インデックス時にこれを行うことができれば、それはより良いと思います。

あなただけのあなたの最後のアプローチが最適なものであると思われる組み合わせ(A_B)とないすべての順列(A_B、B_A)

+0

もちろん、私たちが話しているサイズによっては実現可能かもしれません。私の場合、突然変異のプロセスにはかなりの時間がかかるかもしれないと心配しています。そして、私がさまざまな分野のセットを必要とするならば、提案するnew_fieldのいくつかのバージョンを作らなければなりません。これは私の場合でもメモリ上の問題になります: -/ – Alfe

+0

あなたの答えはLogstashの状況にのみ当てはまると思います。私はLogstashを使用していないにもかかわらず、私の問題を解決したいと思っています;-) – Alfe

+0

そして、組み合わせで再インデックスを作成するのはどうですか? 10個のフィールドがある場合は、各フィールドを9回以上ノーマルに索引付けし、そのフィールドは分析されないフィールドにすることができます。あなたが望んでいない場合は、それらの値を置くScriptフィールドを考えることができますが、冗長なインデックス付きフィールドではパフォーマンスははるかに良いでしょう。 –

1

を必要としています。そして、あなたはupdate your elasticsearch settings次のようにすることができます:デフォルトは60%であり、それはあなたのelasticsearchとクエリで5.9gbあるので、私は75%を選択した

indices.breaker.request.limit: "75%" 
indices.breaker.total.limit: "85%" 

は周り71.1%あなたのログをもとにしている~6.3gbになってきています。

circuit_breaking_exception: [request] Data too large, data for [<reused_arrays>] would be larger than limit of [6348236390/5.9gb]

そして最後にindices.breaker.total.limitelasticsearch documentに応じindices.breaker.fielddata.limitよりも大きくなければなりません。

+0

私が今理解していると思うように、この大規模なデータセットではこの全面的なアプローチが実現できない理由を読むために私自身の答えを参照してください。 – Alfe

関連する問題