記事ディレクトリ
前書き
私は以前にクエリとフィルターで混乱していました。なぜ同じブールが1つの場所でのクエリであり、別の場所でのフィルターであるのですか。
その後、公式ドキュメントを詳しく調べたところ、すべてがクエリであり、次のように区別されていることがわかりました。
- クエリコンテキスト
- フィルターコンテキスト
クエリコンテキストとフィルターコンテキストを区別する理由
効率が異なるため、フィルターコンテキスト内のクエリの方が効率的です。フィルターコンテキストは関連性スコアを計算しないため、ESは高頻度フィルタークエリを自動的にキャッシュします。
フィルタリングコンテキストとは
まず、フィルターは必須であり、ブールクエリのmust_notもフィルターコンテキストで実行されます。
フィルタ
ブールクエリ:
{
"query": {
"bool": {
"filter": [
{
"term": {
"status": "1" }},
{
"range": {
"create_date": {
"lte": "2020-01-01" }}}
]
}
}
}
constant_scoreクエリ:
{
"query": {
"constant_score" : {
"filter" : {
"term" : {
"user" : "tim"}
},
"boost" : 1.2
}
}
}
集約関数では:
{
"aggs" : {
"month" : {
"filter" : {
"term": {
"type": "2" } }
}
}
}
must_not
{
"query": {
"bool" : {
"must_not" : {
"range" : {
"age" : {
"gte" : 18, "lte" : 30 }
}
}
}
}
}
ブールクエリ
の種類 | 説明 |
---|---|
しなければならない | 条件が満たされている必要があること、複数の条件間の関係がであること、および同時に条件が満たされていることを示します |
すべき | 少なくとも1つが一致し、複数の条件間の関係がまたはであることを示し、少なくとも1つが満たされていることを示します |
フィルタ | 条件が満たされている必要があります。必要条件とは異なり、フィルターはフィルター処理コンテキストで実行され、関連性スコアは計算されません |
must_not | 条件が満たされていないこと、フィルタリングコンテキストで実行されていること、および関連性スコアが計算されていないこと |
注:must_notはフィルターコンテキスト内にあります(フィルターコンテキスト実行)
{
"query": {
"bool" : {
"must" : {
"term" : {
"status" : 1 }
},
"filter": {
"term" : {
"type" : "Component" }
},
"must_not" : {
"range" : {
"ctime" : {
"gte" : "2019-12-01", "lte" : "2020-01-01" }
}
},
"should" : [
{
"term" : {
"tag" : "Kafka" } },
{
"term" : {
"tag" : "Elasticsearch" } }
]
}
}
}
上記のように、用語は完全一致を意味する用語クエリを意味し、範囲クエリは範囲一致を意味します。
上記のクエリの意味は、ドキュメントのステータスフィールドが1、タイプフィールドが「コンポーネント」、ctimeフィールドが2019-12-01から2020-01-01の範囲内で、タグフィールドに「Kafka」が含まれている必要があることです。または「Elasticsearch」。
全文検索クエリ
一致
最も一般的に使用される一致は、対応するフィールドのフルテキストインデックスです。
{
"match" : {
"lauguage" : "Java"
}
}
{
"query": {
"match" : {
"message" : {
"query" : "java python ruby"
}
}
}
}
multi_match
multi_matchはmatchに似ていますが、検索する複数のフィールドを指定できます。
{
"query": {
"multi_match" : {
"query": "java python ruby",
"fields": [ "subject", "message" ]
}
}
}
match_all
Match_allはすべてのインデックスフィールドをクエリできます。デフォルトでは、クエリ条件なしでmatch_allが使用されます。
{
"match_all" : {
}
}
match_phrase
match_phraseはmatchと少し似ていますが、2つの大きな違いがあります。
- クエリセグメンテーションの単語は、ドキュメントの対応するフィールドセグメンテーションに表示される必要があります
- 単語の順序も同じである必要があります
{
"query": {
"match_phrase" : {
"message" : "java python ruby"
}
}
}
相対位置は、slopパラメータを使用して調整できます
{
"query": {
"match_phrase": {
"message": {
"query": "java python ruby",
"slop": 2
}
}
}
}
次のクエリ例を参照できます。以下はテストデータです。
上の図に示すように、slopパラメーターなしのクエリ結果です。
上の図に示すように、slopパラメータが2のクエリ結果です。
上の図に示すように、slopパラメータが3のクエリ結果です。
slopパラメーターは、クエリワード内のslop-1ワードを調整するためのものであることがわかります。
match_phrase_prefix
match_phrase_prefixはmatch_phraseと似ていますが、プレフィックスマッチングを実行します
{
"query": {
"match_phrase_prefix" : {
"message" : {
"query" : "java python r"
}
}
}
}
その他の一般的なクエリ
上記で紹介したブールクエリ、全文検索クエリ、関連する用語、範囲、その他のクエリから出てきた他に、よく使用されるクエリがいくつかあります。以下に簡単に紹介します。
条項
これまでは、完全一致を意味する用語クエリについて説明しました。用語と用語は基本的に同じですが、用語を使用すると複数の値を設定できます。1つの値が完全に一致する限り、一致は成功します。
{
"query" : {
"terms" : {
"component" : ["kafka", "elasticsearch"],
"boost" : 1.5
}
}
}
上記のように、コンポーネントフィールドがkafka または elasticsearchと完全に一致する限り、一致は成功します。
Boostはドキュメントの関連性に影響します。1より大きい場合は計算中にドキュメントの関連性が高くなり、1未満の場合は計算中にドキュメントの関連性が低くなります。
terms_set
terms_setクエリには配列が与えられます。ドキュメント内の対応するフィールドに少なくともパラメーター配列内の指定された値が含まれている場合、一致します。
少し複雑に聞こえますが、問題ではありません。例を見て、まずユーザーインデックスを作成してから、次のように2つのドキュメントを追加します。
PUT / user / _doc / 1?refresh
{
"name": "tim",
"hobby": ["看书", "跑步"],
"required_matches": 2
}
PUT / user / _doc / 2?refresh
{
"name": "allen",
"hobby": ["看书", "冥想"],
"required_matches": 2
}
これで、terms_setクエリを実行できます。
GET / user / _search
{
"query": {
"terms_set": {
"hobby.keyword": {
"terms": ["看书", "游泳", "冥想"],
"minimum_should_match_field": "required_matches"
}
}
}
}
上記のように、クエリではhobby.keywordがhobbyの代わりに使用されます。これは、ユーザーマッピングの追加時にマッピングが設定されず、hobbyが自動的にテキストタイプにマッピングされるためですが、自動マッピングでもfieldsパラメーターを使用するため、hobbyを使用できます。検索するキーワード。
問題が心配な場合は、マッピングを直接設定し、キーワードタイプとして趣味を設定できます。
上記の検索では、名前がallenのドキュメントが検索されます。「meditation」を「running」に置き換えると、名前がtimのドキュメントが検索されます。
クエリで値を直接設定するのではなく、最小一致数をドキュメントで設定する必要があることは、さらに痛いです。クエリでは、参照ドキュメント内の最小の一致フィールドを使用します
存在する
{
"query": {
"exists": {
"field": "gid"
}
}
}
ID
{
"query": {
"ids" : {
"values" : ["1", "3", "5", "7", "9"]
}
}
}
接頭辞
プレフィックスの照合は非常に便利な場合があります。たとえば、Lao Wangを探しています。
{
"query": {
"prefix" : {
"name" : "王" }
}
}
ワイルドカード
プレフィックスクエリがニーズを満たせないと思われる場合は、ワイルドカードクエリを検討することもできます。
{
"query": {
"wildcard": {
"name": {
"value": "王*五",
"boost": 1.5
}
}
}
}
ワイルドカードは2つのワイルドカードをサポートします。
- ?は文字と一致することを意味します
- * 0を複数の文字に一致させる
boostの値は関連性に影響を与える可能性があります。1未満の場合はドキュメントの関連性が低くなることを意味し、1より大きい場合はドキュメントの関連性が高くなります。
ワイルドカードが要件を満たしていない場合は、正規表現の正規表現クエリを検討することもできます
ただし、オンライン環境では接頭辞のみを使用することを強くお勧めします。スコアの関連性に影響を与える場合は、ワイルドカードを使用し、ワイルドカードで始めないでください。
constant_score
フィルター処理のみを行う場合は、constant_scoreクエリを検討できます。
{
"query": {
"bool": {
"must": {
"match_all": {
}
},
"filter": {
"term": {
"status": 1
}
}
}
}
}
に相当:
{
"query": {
"constant_score": {
"filter": {
"term": {
"status": 1
}
}
}
}
}