includeとregexを使用して、elasticsearchで用語の集計値の内部を正しくクエリする方法は?

mclenithan

集計結果を効率的に除外/検索するにはどうすればよいですか?

ElasticSearchに100万のドキュメントがあると想像してください。これらのドキュメントには、multi_field(キーワード、テキスト)がありtagsます。

{
  ...
  tags: ['Race', 'Racing', 'Mountain Bike', 'Horizontal'],
  ...
},
{
  ...
  tags: ['Tracey Chapman', 'Silverfish', 'Blue'],
  ...
},
{
  ...
  tags: ['Surfing', 'Race', 'Disgrace'],
  ...
},

これらの値をクエリに対するフィルター(ファセット)として使用して、このタグを含むドキュメントのみをプルできます。

...
"filter": [
  {
    "terms": {
      "tags": [
        "Race"
      ]
    }
  },
  ...
]

ただし、ユーザーが可能なタグフィルターを照会できるようにする必要があります。したがって、ユーザーが入力するとrace、(前の例の)戻り値が表示され['Race', 'Tracey Chapman', 'Disgrace']ます。このようにして、ユーザーは使用するフィルターを照会できます。これを実現するには、集計を使用する必要がありました。

{
  "aggs": {
    "topics": {
      "terms": {
        "field": "tags",
        "include": ".*[Rr][Aa][Cc][Ee].*", // I have to dynamically form this
        "size": 6
      }
    }
  },
  "size": 0
}

これは私に必要なものを正確に与えてくれます!しかし、それは遅いです、非常に遅いです。execute_hintを追加しようとしましたが、役に立ちません。

「集計の前にクエリを使用するだけです!」と思うかもしれません。ただし、問題は、そのクエリ内のすべてのドキュメントのすべての値を取得することです。つまり、まったく関係のないタグを表示することができます。race集計の前にクエリを実行し、include正規表現を使用しなかった場合、次のような他のすべての値になります。'Horizontal', etc...

この集計を書き換えてより高速に動作させるにはどうすればよいですか?これを書くためのより良い方法はありますか?値のためだけに別のインデックスを作成する必要がありますか?(悲しい顔)これは一般的な問題のようですが、ドキュメントやグーグルで答えが見つかりませんでした。

ジョー・ソロシン

値のためだけに個別のインデックスは必要ありません...

これが私の見解です:

  1. 正規表現で行っていることは、基本的に、トークナイザーによって行われるべきことです。つまり後でターゲットにできるように部分文字列(またはNグラム)を作成します。
    これは、キーワードRaceをn-gramにトークン化する必要があることを意味し["rac", "race", "ace"]ます。(3文字未満にすることは実際には意味がありません。ほとんどのオートコンプリートライブラリは、一致する可能性のあるバルーンが速すぎるため、3文字未満を無視することを選択します。)

ElasticsearchはN-grammax_ngram_diffトークナイザーを提供しますが、妥当な数のngramをキャッチしたいので、呼び出されるデフォルトのインデックスレベル設定を1から(任意に)10に増やす必要があります

PUT tagindex
{
  "settings": {
    "index": {
      "max_ngram_diff": 10
    },
    "analysis": {
      "analyzer": {
        "my_ngrams_analyzer": {
          "tokenizer": "my_ngrams",
          "filter": [ "lowercase" ]
        }
      },
      "tokenizer": {
        "my_ngrams": {
          "type": "ngram",
          "min_gram": 3,
          "max_gram": 10,
          "token_chars": [ "letter", "digit" ]
        }
      }
    }
  },
  { "mappings": ... }                                 --> see below
}
  1. あなたの場合はtags、フィールドがキーワードのリストである、それはその場に集約するだけではできませんせずに頼らinclude完全一致または(あなたがすでに使用している)正規表現のいずれかになりますオプション。現在、完全一致を保証することはできませんが、正規表現もしたくありません。それでは、なぜ私たちが使用する必要があることを、ネストされたリストwhich'll個別に各タグの治療を

現在、ネストされたリストにはオブジェクトが含まれていると予想されるため、

{
  "tags": ["Race", "Racing", "Mountain Bike", "Horizontal"]
}

に変換する必要があります

{
  "tags": [
    { "tag": "Race" },
    { "tag": "Racing" },
    { "tag": "Mountain Bike" },
    { "tag": "Horizontal" }
  ]
}

その後、元のタグをそのまま維持しながら、検索するフィールドと集計するフィールドを追加して、マルチフィールドマッピングを続行します.tokenized.keyword

  "index": { ... },
  "analysis": { ... },
  "mappings": {
    "properties": {
      "tags": {
        "type": "nested",
        "properties": {
          "tag": {
            "type": "text",
            "fields": {
              "tokenized": {
                "type": "text",
                "analyzer": "my_ngrams_analyzer"
              },
              "keyword": {
                "type": "keyword"
              }
            }
          }
        }
      }
    }
  }

次に、調整したタグのドキュメントを追加します。

POST tagindex/_doc
{"tags":[{"tag":"Race"},{"tag":"Racing"},{"tag":"Mountain Bike"},{"tag":"Horizontal"}]}

POST tagindex/_doc
{"tags":[{"tag":"Tracey Chapman"},{"tag":"Silverfish"},{"tag":"Blue"}]}

POST tagindex/_doc
{"tags":[{"tag":"Surfing"},{"tag":"Race"},{"tag":"Disgrace"}]}

ネストされた フィルター 用語の集計を適用します

GET tagindex/_search
{
  "aggs": {
    "topics_parent": {
      "nested": {
        "path": "tags"
      },
      "aggs": {
        "topics": {
          "filter": {
            "term": {
              "tags.tag.tokenized": "race"
            }
          },
          "aggs": {
            "topics": {
              "terms": {
                "field": "tags.tag.keyword",
                "size": 100
              }
            }
          }
        }
      }
    }
  },
  "size": 0
}

降伏

{
  ...
  "topics_parent" : {
    ...
    "topics" : {
      ...
      "topics" : {
        ...
        "buckets" : [
          {
            "key" : "Race",
            "doc_count" : 2
          },
          {
            "key" : "Disgrace",
            "doc_count" : 1
          },
          {
            "key" : "Tracey Chapman",
            "doc_count" : 1
          }
        ]
      }
    }
  }
}

警告

  • これを機能させるには、インデックスを再作成する必要があります
  • ngramは、ストレージのフットプリントを増加させます-ドキュメントごとのタグの数によっては、問題になる可能性があります
  • ネストされたフィールドは内部的に「個別のドキュメント」として扱われるため、これはディスクスペースにも影響します

PS:これは興味深いユースケースです。実装がどのように進んだか教えてください!

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

分類Dev

集計を使用してクエリ結果の用語のドキュメント頻度を取得する

分類Dev

集計クエリを使用して null 以外の値のみを表示する方法は?

分類Dev

Elasticsearchの用語集計クエリからすべてのdoc_countsの合計を取得するにはどうすればよいですか?

分類Dev

Golangでmgoを使用して次のMongo集計クエリを作成する方法

分類Dev

Elasticsearchでは、オプションの追加のクエリ用語を使用して、配列の1つと一致する必要があります

分類Dev

ElasticSearchの用語集計クエリで追加のフィールドを返す

分類Dev

Elasticsearchクエリ-タイムスタンプを集計し、用語でフィルタリングする方法は?

分類Dev

PostgreSQLでLIMITを正しく使用して、IDごとに1行のみをクエリする方法

分類Dev

PostgreSQLでLIMITを正しく使用して、IDごとに1行のみをクエリする方法

分類Dev

groupby関数と集計関数を使用してSQLクエリの行数を単一の数値として返す方法は?

分類Dev

値の合計を条件として使用する(SQLクエリ)

分類Dev

用語集約を使用して検索を実行するときに、実際の値(小文字ではない)を返す方法は?

分類Dev

それは可能ですか?クエリのみを使用して数値とデータベース列の値を合計する方法

分類Dev

Elasticsearchクエリで1つまたは複数の1つの値を持つ用語を使用する

分類Dev

Elasticsearchを使用してオブジェクトの値をクエリする方法

分類Dev

ElasticSearchクエリ用語はすべてのデータを返します

分類Dev

Tinkerpop3グラフでelasticsearchを使用して頂点のすべての値をクエリする方法

分類Dev

Tinkerpop3グラフでelasticsearchを使用して頂点のすべての値をクエリする方法

分類Dev

用語クエリは0の結果を返しますelasticsearch

分類Dev

Linux用のQtとDcmtkを正しくリンクする方法は?

分類Dev

DAXクエリを使用してPowerBIで増分値を計算する方法は?

分類Dev

述語と同じコレクションの値を使用して、コレクションから集計値を取得する方法

分類Dev

ElasticsearchをデータソースとしてGrafanaのテンプレートを使用した用語の集計

分類Dev

固定されていない列のクロス集計をサブクエリとして使用することはできません。(エラー3637)

分類Dev

フィールドではなく、用語に欠落している集計を使用する

分類Dev

単一のクエリで結合関数と集計関数を使用して、テーブル内の複数の行を更新する方法

分類Dev

CosmosAPIを使用してMongoDB集計クエリの40MBクエリ制限を排除する方法

分類Dev

合計集計を使用したElasticsearchクエリの問題

分類Dev

単一のキーの値の内部でapplyとintを正しく使用する方法

Related 関連記事

  1. 1

    集計を使用してクエリ結果の用語のドキュメント頻度を取得する

  2. 2

    集計クエリを使用して null 以外の値のみを表示する方法は?

  3. 3

    Elasticsearchの用語集計クエリからすべてのdoc_countsの合計を取得するにはどうすればよいですか?

  4. 4

    Golangでmgoを使用して次のMongo集計クエリを作成する方法

  5. 5

    Elasticsearchでは、オプションの追加のクエリ用語を使用して、配列の1つと一致する必要があります

  6. 6

    ElasticSearchの用語集計クエリで追加のフィールドを返す

  7. 7

    Elasticsearchクエリ-タイムスタンプを集計し、用語でフィルタリングする方法は?

  8. 8

    PostgreSQLでLIMITを正しく使用して、IDごとに1行のみをクエリする方法

  9. 9

    PostgreSQLでLIMITを正しく使用して、IDごとに1行のみをクエリする方法

  10. 10

    groupby関数と集計関数を使用してSQLクエリの行数を単一の数値として返す方法は?

  11. 11

    値の合計を条件として使用する(SQLクエリ)

  12. 12

    用語集約を使用して検索を実行するときに、実際の値(小文字ではない)を返す方法は?

  13. 13

    それは可能ですか?クエリのみを使用して数値とデータベース列の値を合計する方法

  14. 14

    Elasticsearchクエリで1つまたは複数の1つの値を持つ用語を使用する

  15. 15

    Elasticsearchを使用してオブジェクトの値をクエリする方法

  16. 16

    ElasticSearchクエリ用語はすべてのデータを返します

  17. 17

    Tinkerpop3グラフでelasticsearchを使用して頂点のすべての値をクエリする方法

  18. 18

    Tinkerpop3グラフでelasticsearchを使用して頂点のすべての値をクエリする方法

  19. 19

    用語クエリは0の結果を返しますelasticsearch

  20. 20

    Linux用のQtとDcmtkを正しくリンクする方法は?

  21. 21

    DAXクエリを使用してPowerBIで増分値を計算する方法は?

  22. 22

    述語と同じコレクションの値を使用して、コレクションから集計値を取得する方法

  23. 23

    ElasticsearchをデータソースとしてGrafanaのテンプレートを使用した用語の集計

  24. 24

    固定されていない列のクロス集計をサブクエリとして使用することはできません。(エラー3637)

  25. 25

    フィールドではなく、用語に欠落している集計を使用する

  26. 26

    単一のクエリで結合関数と集計関数を使用して、テーブル内の複数の行を更新する方法

  27. 27

    CosmosAPIを使用してMongoDB集計クエリの40MBクエリ制限を排除する方法

  28. 28

    合計集計を使用したElasticsearchクエリの問題

  29. 29

    単一のキーの値の内部でapplyとintを正しく使用する方法

ホットタグ

アーカイブ