Multi-match query

multi_match クエリは、match クエリ を基にして、複数フィールドのクエリを可能にします:

Php

  1. $params = [
  2. 'body' => [
  3. 'query' => [
  4. 'multi_match' => [
  5. 'query' => 'this is a test',
  6. 'fields' => [
  7. 'subject',
  8. 'message',
  9. ],
  10. ],
  11. ],
  12. ],
  13. ];
  14. $response = $client->search($params);

Python

  1. resp = client.search(
  2. query={
  3. "multi_match": {
  4. "query": "this is a test",
  5. "fields": [
  6. "subject",
  7. "message"
  8. ]
  9. }
  10. },
  11. )
  12. print(resp)

Ruby

  1. response = client.search(
  2. body: {
  3. query: {
  4. multi_match: {
  5. query: 'this is a test',
  6. fields: [
  7. 'subject',
  8. 'message'
  9. ]
  10. }
  11. }
  12. }
  13. )
  14. puts response

Go

  1. res, err := es.Search(
  2. es.Search.WithBody(strings.NewReader(`{
  3. "query": {
  4. "multi_match": {
  5. "query": "this is a test",
  6. "fields": [
  7. "subject",
  8. "message"
  9. ]
  10. }
  11. }
  12. }`)),
  13. es.Search.WithPretty(),
  14. )
  15. fmt.Println(res, err)

Js

  1. const response = await client.search({
  2. query: {
  3. multi_match: {
  4. query: "this is a test",
  5. fields: ["subject", "message"],
  6. },
  7. },
  8. });
  9. console.log(response);

Console

  1. GET /_search
  2. {
  3. "query": {
  4. "multi_match" : {
  5. "query": "this is a test",
  6. "fields": [ "subject", "message" ]
  7. }
  8. }
  9. }
クエリ文字列。
クエリ対象のフィールド。

fields and per-field boosting

フィールドはワイルドカードで指定できます。例えば:

Php

  1. $params = [
  2. 'body' => [
  3. 'query' => [
  4. 'multi_match' => [
  5. 'query' => 'Will Smith',
  6. 'fields' => [
  7. 'title',
  8. '*_name',
  9. ],
  10. ],
  11. ],
  12. ],
  13. ];
  14. $response = $client->search($params);

Python

  1. resp = client.search(
  2. query={
  3. "multi_match": {
  4. "query": "Will Smith",
  5. "fields": [
  6. "title",
  7. "*_name"
  8. ]
  9. }
  10. },
  11. )
  12. print(resp)

Ruby

  1. response = client.search(
  2. body: {
  3. query: {
  4. multi_match: {
  5. query: 'Will Smith',
  6. fields: [
  7. 'title',
  8. '*_name'
  9. ]
  10. }
  11. }
  12. }
  13. )
  14. puts response

Go

  1. res, err := es.Search(
  2. es.Search.WithBody(strings.NewReader(`{
  3. "query": {
  4. "multi_match": {
  5. "query": "Will Smith",
  6. "fields": [
  7. "title",
  8. "*_name"
  9. ]
  10. }
  11. }
  12. }`)),
  13. es.Search.WithPretty(),
  14. )
  15. fmt.Println(res, err)

Js

  1. const response = await client.search({
  2. query: {
  3. multi_match: {
  4. query: "Will Smith",
  5. fields: ["title", "*_name"],
  6. },
  7. },
  8. });
  9. console.log(response);

Console

  1. GET /_search
  2. {
  3. "query": {
  4. "multi_match" : {
  5. "query": "Will Smith",
  6. "fields": [ "title", "*_name" ]
  7. }
  8. }
  9. }
titlefirst_namelast_name フィールドをクエリします。

個々のフィールドはキャレット (^) 表記でブーストできます:

Php

  1. $params = [
  2. 'body' => [
  3. 'query' => [
  4. 'multi_match' => [
  5. 'query' => 'this is a test',
  6. 'fields' => [
  7. 'subject^3',
  8. 'message',
  9. ],
  10. ],
  11. ],
  12. ],
  13. ];
  14. $response = $client->search($params);

Python

  1. resp = client.search(
  2. query={
  3. "multi_match": {
  4. "query": "this is a test",
  5. "fields": [
  6. "subject^3",
  7. "message"
  8. ]
  9. }
  10. },
  11. )
  12. print(resp)

Ruby

  1. response = client.search(
  2. body: {
  3. query: {
  4. multi_match: {
  5. query: 'this is a test',
  6. fields: [
  7. 'subject^3',
  8. 'message'
  9. ]
  10. }
  11. }
  12. }
  13. )
  14. puts response

Go

  1. res, err := es.Search(
  2. es.Search.WithBody(strings.NewReader(`{
  3. "query": {
  4. "multi_match": {
  5. "query": "this is a test",
  6. "fields": [
  7. "subject^3",
  8. "message"
  9. ]
  10. }
  11. }
  12. }`)),
  13. es.Search.WithPretty(),
  14. )
  15. fmt.Println(res, err)

Js

  1. const response = await client.search({
  2. query: {
  3. multi_match: {
  4. query: "this is a test",
  5. fields: ["subject^3", "message"],
  6. },
  7. },
  8. });
  9. console.log(response);

Console

  1. GET /_search
  2. {
  3. "query": {
  4. "multi_match" : {
  5. "query" : "this is a test",
  6. "fields" : [ "subject^3", "message" ]
  7. }
  8. }
  9. }
subject フィールドのスコアを3倍にしますが、message フィールドのスコアは変更しません。

fields が提供されていない場合、multi_match クエリは index.query.default_field インデックス設定にデフォルトし、さらに * にデフォルトします。 * は、用語クエリに適格なマッピング内のすべてのフィールドを抽出し、メタデータフィールドをフィルタリングします。抽出されたすべてのフィールドは、クエリを構築するために組み合わされます。

Field number limit

デフォルトでは、クエリに含まれる句の数に制限があります。この制限は、indices.query.bool.max_clause_count 設定によって定義され、デフォルトは 4096 です。マルチマッチクエリの場合、句の数はフィールドの数と用語の数を掛けたものとして計算されます。

Types of multi_match query:

multi_match クエリの内部実行方法は、type パラメータに依存し、次のように設定できます:

best_fields (デフォルト) 任意のフィールドに一致するドキュメントを見つけますが、_score は最良のフィールドから使用されます。 best_fields を参照してください。
most_fields 任意のフィールドに一致するドキュメントを見つけ、各フィールドから _score を組み合わせます。 most_fields を参照してください。
cross_fields 同じ analyzer を持つフィールドを1つの大きなフィールドのように扱います。任意のフィールドで各単語を探します。 cross_fields を参照してください。
phrase 各フィールドで match_phrase クエリを実行し、最良のフィールドから _score を使用します。 phrasephrase_prefix を参照してください。
phrase_prefix 各フィールドで match_phrase_prefix クエリを実行し、最良のフィールドから _score を使用します。 phrasephrase_prefix を参照してください。

| bool_prefix | 各フィールドで match_bool_prefix クエリを作成し、各フィールドから _score を組み合わせます。 bool_prefix を参照してください。

best_fields

best_fields タイプは、同じフィールドで最もよく見つかる複数の単語を検索する際に最も便利です。例えば、「茶色の狐」は、1つのフィールドに「茶色」と別のフィールドに「狐」があるよりも意味があります。

best_fields タイプは、各フィールドに対して match クエリ を生成し、それらを dis_max クエリでラップして、最も一致するフィールドを見つけます。例えば、このクエリ:

Php

  1. $params = [
  2. 'body' => [
  3. 'query' => [
  4. 'multi_match' => [
  5. 'query' => 'brown fox',
  6. 'type' => 'best_fields',
  7. 'fields' => [
  8. 'subject',
  9. 'message',
  10. ],
  11. 'tie_breaker' => 0.3,
  12. ],
  13. ],
  14. ],
  15. ];
  16. $response = $client->search($params);

Python

  1. resp = client.search(
  2. query={
  3. "multi_match": {
  4. "query": "brown fox",
  5. "type": "best_fields",
  6. "fields": [
  7. "subject",
  8. "message"
  9. ],
  10. "tie_breaker": 0.3
  11. }
  12. },
  13. )
  14. print(resp)

Ruby

  1. response = client.search(
  2. body: {
  3. query: {
  4. multi_match: {
  5. query: 'brown fox',
  6. type: 'best_fields',
  7. fields: [
  8. 'subject',
  9. 'message'
  10. ],
  11. tie_breaker: 0.3
  12. }
  13. }
  14. }
  15. )
  16. puts response

Go

  1. res, err := es.Search(
  2. es.Search.WithBody(strings.NewReader(`{
  3. "query": {
  4. "multi_match": {
  5. "query": "brown fox",
  6. "type": "best_fields",
  7. "fields": [
  8. "subject",
  9. "message"
  10. ],
  11. "tie_breaker": 0.3
  12. }
  13. }
  14. }`)),
  15. es.Search.WithPretty(),
  16. )
  17. fmt.Println(res, err)

Js

  1. const response = await client.search({
  2. query: {
  3. multi_match: {
  4. query: "brown fox",
  5. type: "best_fields",
  6. fields: ["subject", "message"],
  7. tie_breaker: 0.3,
  8. },
  9. },
  10. });
  11. console.log(response);

Console

  1. GET /_search
  2. {
  3. "query": {
  4. "multi_match" : {
  5. "query": "brown fox",
  6. "type": "best_fields",
  7. "fields": [ "subject", "message" ],
  8. "tie_breaker": 0.3
  9. }
  10. }
  11. }

実行されるのは:

Php

  1. $params = [
  2. 'body' => [
  3. 'query' => [
  4. 'dis_max' => [
  5. 'queries' => [
  6. [
  7. 'match' => [
  8. 'subject' => 'brown fox',
  9. ],
  10. ],
  11. [
  12. 'match' => [
  13. 'message' => 'brown fox',
  14. ],
  15. ],
  16. ],
  17. 'tie_breaker' => 0.3,
  18. ],
  19. ],
  20. ],
  21. ];
  22. $response = $client->search($params);

Python

  1. resp = client.search(
  2. query={
  3. "dis_max": {
  4. "queries": [
  5. {
  6. "match": {
  7. "subject": "brown fox"
  8. }
  9. },
  10. {
  11. "match": {
  12. "message": "brown fox"
  13. }
  14. }
  15. ],
  16. "tie_breaker": 0.3
  17. }
  18. },
  19. )
  20. print(resp)

Ruby

  1. response = client.search(
  2. body: {
  3. query: {
  4. dis_max: {
  5. queries: [
  6. {
  7. match: {
  8. subject: 'brown fox'
  9. }
  10. },
  11. {
  12. match: {
  13. message: 'brown fox'
  14. }
  15. }
  16. ],
  17. tie_breaker: 0.3
  18. }
  19. }
  20. }
  21. )
  22. puts response

Go

  1. res, err := es.Search(
  2. es.Search.WithBody(strings.NewReader(`{
  3. "query": {
  4. "dis_max": {
  5. "queries": [
  6. {
  7. "match": {
  8. "subject": "brown fox"
  9. }
  10. },
  11. {
  12. "match": {
  13. "message": "brown fox"
  14. }
  15. }
  16. ],
  17. "tie_breaker": 0.3
  18. }
  19. }
  20. }`)),
  21. es.Search.WithPretty(),
  22. )
  23. fmt.Println(res, err)

Js

  1. const response = await client.search({
  2. query: {
  3. dis_max: {
  4. queries: [
  5. {
  6. match: {
  7. subject: "brown fox",
  8. },
  9. },
  10. {
  11. match: {
  12. message: "brown fox",
  13. },
  14. },
  15. ],
  16. tie_breaker: 0.3,
  17. },
  18. },
  19. });
  20. console.log(response);

Console

  1. GET /_search
  2. {
  3. "query": {
  4. "dis_max": {
  5. "queries": [
  6. { "match": { "subject": "brown fox" }},
  7. { "match": { "message": "brown fox" }}
  8. ],
  9. "tie_breaker": 0.3
  10. }
  11. }
  12. }

通常、best_fields タイプは 単一 の最良の一致フィールドのスコアを使用しますが、tie_breaker が指定されている場合、スコアは次のように計算されます:

  • 最良の一致フィールドからのスコア
  • 他のすべての一致フィールドに対して tie_breaker * _score

また、analyzerboostoperatorminimum_should_matchfuzzinesslenientprefix_lengthmax_expansionsfuzzy_rewritezero_terms_queryauto_generate_synonyms_phrase_queryfuzzy_transpositions が受け入れられます。これは、match query で説明されています。

operator and minimum_should_match

best_fieldsmost_fields タイプは フィールド中心 です。つまり、各フィールドごとに match クエリを生成します。これは、operatorminimum_should_match パラメータが各フィールドに個別に適用されることを意味し、これはおそらく望ましくない結果です。

このクエリを例に取ります:

Php

  1. $params = [
  2. 'body' => [
  3. 'query' => [
  4. 'multi_match' => [
  5. 'query' => 'Will Smith',
  6. 'type' => 'best_fields',
  7. 'fields' => [
  8. 'first_name',
  9. 'last_name',
  10. ],
  11. 'operator' => 'and',
  12. ],
  13. ],
  14. ],
  15. ];
  16. $response = $client->search($params);

Python

  1. resp = client.search(
  2. query={
  3. "multi_match": {
  4. "query": "Will Smith",
  5. "type": "best_fields",
  6. "fields": [
  7. "first_name",
  8. "last_name"
  9. ],
  10. "operator": "and"
  11. }
  12. },
  13. )
  14. print(resp)

Ruby

  1. response = client.search(
  2. body: {
  3. query: {
  4. multi_match: {
  5. query: 'Will Smith',
  6. type: 'best_fields',
  7. fields: [
  8. 'first_name',
  9. 'last_name'
  10. ],
  11. operator: 'and'
  12. }
  13. }
  14. }
  15. )
  16. puts response

Go

  1. res, err := es.Search(
  2. es.Search.WithBody(strings.NewReader(`{
  3. "query": {
  4. "multi_match": {
  5. "query": "Will Smith",
  6. "type": "best_fields",
  7. "fields": [
  8. "first_name",
  9. "last_name"
  10. ],
  11. "operator": "and"
  12. }
  13. }
  14. }`)),
  15. es.Search.WithPretty(),
  16. )
  17. fmt.Println(res, err)

Js

  1. const response = await client.search({
  2. query: {
  3. multi_match: {
  4. query: "Will Smith",
  5. type: "best_fields",
  6. fields: ["first_name", "last_name"],
  7. operator: "and",
  8. },
  9. },
  10. });
  11. console.log(response);

Console

  1. GET /_search
  2. {
  3. "query": {
  4. "multi_match" : {
  5. "query": "Will Smith",
  6. "type": "best_fields",
  7. "fields": [ "first_name", "last_name" ],
  8. "operator": "and"
  9. }
  10. }
  11. }
すべての用語が存在する必要があります。

このクエリは次のように実行されます:

  1. (+first_name:will +first_name:smith)
  2. | (+last_name:will +last_name:smith)

言い換えれば、すべての用語単一のフィールド に存在する必要があります。

combined_fields クエリは、operatorminimum_should_match を用語ごとに処理する用語中心のアプローチを提供します。他のマルチマッチモード cross_fields もこの問題に対処します。

most_fields

most_fields タイプは、異なる方法で分析された同じテキストを含む複数のフィールドをクエリする際に最も便利です。例えば、メインフィールドには同義語、ステミング、ダイアクリティックなしの用語が含まれる場合があります。2番目のフィールドには元の用語が含まれ、3番目のフィールドにはシングルが含まれるかもしれません。すべてのフィールドからスコアを組み合わせることで、メインフィールドでできるだけ多くのドキュメントに一致させることができますが、2番目と3番目のフィールドを使用して、最も類似した結果をリストの上位に押し上げます。

このクエリ:

Php

  1. $params = [
  2. 'body' => [
  3. 'query' => [
  4. 'multi_match' => [
  5. 'query' => 'quick brown fox',
  6. 'type' => 'most_fields',
  7. 'fields' => [
  8. 'title',
  9. 'title.original',
  10. 'title.shingles',
  11. ],
  12. ],
  13. ],
  14. ],
  15. ];
  16. $response = $client->search($params);

Python

  1. resp = client.search(
  2. query={
  3. "multi_match": {
  4. "query": "quick brown fox",
  5. "type": "most_fields",
  6. "fields": [
  7. "title",
  8. "title.original",
  9. "title.shingles"
  10. ]
  11. }
  12. },
  13. )
  14. print(resp)

Ruby

  1. response = client.search(
  2. body: {
  3. query: {
  4. multi_match: {
  5. query: 'quick brown fox',
  6. type: 'most_fields',
  7. fields: [
  8. 'title',
  9. 'title.original',
  10. 'title.shingles'
  11. ]
  12. }
  13. }
  14. }
  15. )
  16. puts response

Go

  1. res, err := es.Search(
  2. es.Search.WithBody(strings.NewReader(`{
  3. "query": {
  4. "multi_match": {
  5. "query": "quick brown fox",
  6. "type": "most_fields",
  7. "fields": [
  8. "title",
  9. "title.original",
  10. "title.shingles"
  11. ]
  12. }
  13. }
  14. }`)),
  15. es.Search.WithPretty(),
  16. )
  17. fmt.Println(res, err)

Js

  1. const response = await client.search({
  2. query: {
  3. multi_match: {
  4. query: "quick brown fox",
  5. type: "most_fields",
  6. fields: ["title", "title.original", "title.shingles"],
  7. },
  8. },
  9. });
  10. console.log(response);

Console

  1. GET /_search
  2. {
  3. "query": {
  4. "multi_match" : {
  5. "query": "quick brown fox",
  6. "type": "most_fields",
  7. "fields": [ "title", "title.original", "title.shingles" ]
  8. }
  9. }
  10. }

実行されるのは:

Php

  1. $params = [
  2. 'body' => [
  3. 'query' => [
  4. 'bool' => [
  5. 'should' => [
  6. [
  7. 'match' => [
  8. 'title' => 'quick brown fox',
  9. ],
  10. ],
  11. [
  12. 'match' => [
  13. 'title.original' => 'quick brown fox',
  14. ],
  15. ],
  16. [
  17. 'match' => [
  18. 'title.shingles' => 'quick brown fox',
  19. ],
  20. ],
  21. ],
  22. ],
  23. ],
  24. ],
  25. ];
  26. $response = $client->search($params);

Python

  1. resp = client.search(
  2. query={
  3. "bool": {
  4. "should": [
  5. {
  6. "match": {
  7. "title": "quick brown fox"
  8. }
  9. },
  10. {
  11. "match": {
  12. "title.original": "quick brown fox"
  13. }
  14. },
  15. {
  16. "match": {
  17. "title.shingles": "quick brown fox"
  18. }
  19. }
  20. ]
  21. }
  22. },
  23. )
  24. print(resp)

Ruby

  1. response = client.search(
  2. body: {
  3. query: {
  4. bool: {
  5. should: [
  6. {
  7. match: {
  8. title: 'quick brown fox'
  9. }
  10. },
  11. {
  12. match: {
  13. 'title.original' => 'quick brown fox'
  14. }
  15. },
  16. {
  17. match: {
  18. 'title.shingles' => 'quick brown fox'
  19. }
  20. }
  21. ]
  22. }
  23. }
  24. }
  25. )
  26. puts response

Go

  1. res, err := es.Search(
  2. es.Search.WithBody(strings.NewReader(`{
  3. "query": {
  4. "bool": {
  5. "should": [
  6. {
  7. "match": {
  8. "title": "quick brown fox"
  9. }
  10. },
  11. {
  12. "match": {
  13. "title.original": "quick brown fox"
  14. }
  15. },
  16. {
  17. "match": {
  18. "title.shingles": "quick brown fox"
  19. }
  20. }
  21. ]
  22. }
  23. }
  24. }`)),
  25. es.Search.WithPretty(),
  26. )
  27. fmt.Println(res, err)

Js

  1. const response = await client.search({
  2. query: {
  3. bool: {
  4. should: [
  5. {
  6. match: {
  7. title: "quick brown fox",
  8. },
  9. },
  10. {
  11. match: {
  12. "title.original": "quick brown fox",
  13. },
  14. },
  15. {
  16. match: {
  17. "title.shingles": "quick brown fox",
  18. },
  19. },
  20. ],
  21. },
  22. },
  23. });
  24. console.log(response);

Console

  1. GET /_search
  2. {
  3. "query": {
  4. "bool": {
  5. "should": [
  6. { "match": { "title": "quick brown fox" }},
  7. { "match": { "title.original": "quick brown fox" }},
  8. { "match": { "title.shingles": "quick brown fox" }}
  9. ]
  10. }
  11. }
  12. }

match 句からのスコアは、bool クエリのように合計されます。

また、analyzerboostoperatorminimum_should_matchfuzzinesslenientprefix_lengthmax_expansionsfuzzy_rewrite が受け入れられます。

phrase and phrase_prefix

phrasephrase_prefix タイプは、best_fields と同様に動作しますが、match_phrase または match_phrase_prefix クエリを使用します。match クエリの代わりに。

このクエリ:

Php

  1. $params = [
  2. 'body' => [
  3. 'query' => [
  4. 'multi_match' => [
  5. 'query' => 'quick brown f',
  6. 'type' => 'phrase_prefix',
  7. 'fields' => [
  8. 'subject',
  9. 'message',
  10. ],
  11. ],
  12. ],
  13. ],
  14. ];
  15. $response = $client->search($params);

Python

  1. resp = client.search(
  2. query={
  3. "multi_match": {
  4. "query": "quick brown f",
  5. "type": "phrase_prefix",
  6. "fields": [
  7. "subject",
  8. "message"
  9. ]
  10. }
  11. },
  12. )
  13. print(resp)

Ruby

  1. response = client.search(
  2. body: {
  3. query: {
  4. multi_match: {
  5. query: 'quick brown f',
  6. type: 'phrase_prefix',
  7. fields: [
  8. 'subject',
  9. 'message'
  10. ]
  11. }
  12. }
  13. }
  14. )
  15. puts response

Go

  1. res, err := es.Search(
  2. es.Search.WithBody(strings.NewReader(`{
  3. "query": {
  4. "multi_match": {
  5. "query": "quick brown f",
  6. "type": "phrase_prefix",
  7. "fields": [
  8. "subject",
  9. "message"
  10. ]
  11. }
  12. }
  13. }`)),
  14. es.Search.WithPretty(),
  15. )
  16. fmt.Println(res, err)

Js

  1. const response = await client.search({
  2. query: {
  3. multi_match: {
  4. query: "quick brown f",
  5. type: "phrase_prefix",
  6. fields: ["subject", "message"],
  7. },
  8. },
  9. });
  10. console.log(response);

Console

  1. GET /_search
  2. {
  3. "query": {
  4. "multi_match" : {
  5. "query": "quick brown f",
  6. "type": "phrase_prefix",
  7. "fields": [ "subject", "message" ]
  8. }
  9. }
  10. }

実行されるのは:

Php

  1. $params = [
  2. 'body' => [
  3. 'query' => [
  4. 'dis_max' => [
  5. 'queries' => [
  6. [
  7. 'match_phrase_prefix' => [
  8. 'subject' => 'quick brown f',
  9. ],
  10. ],
  11. [
  12. 'match_phrase_prefix' => [
  13. 'message' => 'quick brown f',
  14. ],
  15. ],
  16. ],
  17. ],
  18. ],
  19. ],
  20. ];
  21. $response = $client->search($params);

Python

  1. resp = client.search(
  2. query={
  3. "dis_max": {
  4. "queries": [
  5. {
  6. "match_phrase_prefix": {
  7. "subject": "quick brown f"
  8. }
  9. },
  10. {
  11. "match_phrase_prefix": {
  12. "message": "quick brown f"
  13. }
  14. }
  15. ]
  16. }
  17. },
  18. )
  19. print(resp)

Ruby

  1. response = client.search(
  2. body: {
  3. query: {
  4. dis_max: {
  5. queries: [
  6. {
  7. match_phrase_prefix: {
  8. subject: 'quick brown f'
  9. }
  10. },
  11. {
  12. match_phrase_prefix: {
  13. message: 'quick brown f'
  14. }
  15. }
  16. ]
  17. }
  18. }
  19. }
  20. )
  21. puts response

Go

  1. res, err := es.Search(
  2. es.Search.WithBody(strings.NewReader(`{
  3. "query": {
  4. "dis_max": {
  5. "queries": [
  6. {
  7. "match_phrase_prefix": {
  8. "subject": "quick brown f"
  9. }
  10. },
  11. {
  12. "match_phrase_prefix": {
  13. "message": "quick brown f"
  14. }
  15. }
  16. ]
  17. }
  18. }
  19. }`)),
  20. es.Search.WithPretty(),
  21. )
  22. fmt.Println(res, err)

Js

  1. const response = await client.search({
  2. query: {
  3. dis_max: {
  4. queries: [
  5. {
  6. match_phrase_prefix: {
  7. subject: "quick brown f",
  8. },
  9. },
  10. {
  11. match_phrase_prefix: {
  12. message: "quick brown f",
  13. },
  14. },
  15. ],
  16. },
  17. },
  18. });
  19. console.log(response);

Console

  1. GET /_search
  2. {
  3. "query": {
  4. "dis_max": {
  5. "queries": [
  6. { "match_phrase_prefix": { "subject": "quick brown f" }},
  7. { "match_phrase_prefix": { "message": "quick brown f" }}
  8. ]
  9. }
  10. }
  11. }

また、analyzer 、[boost] 、[lenient] 、[zero_terms_query] が Match で説明されているようにサポートされており、[slop] は Match phrase で説明されています。 phrase_prefix タイプは、max_expansions も受け入れます。

phrase, phrase_prefix and fuzziness

fuzziness パラメータは、phrase または phrase_prefix タイプと一緒に使用できません。

cross_fields

cross_fields タイプは、複数のフィールドが 一致するべき 構造化ドキュメントで特に便利です。例えば、first_namelast_name フィールドを「ウィル・スミス」でクエリすると、最良の一致は1つのフィールドに「ウィル」があり、別のフィールドに「スミス」がある可能性が高いです。

これは most_fields の仕事のように思えますが、そのアプローチには2つの問題があります。最初の問題は、operatorminimum_should_match がフィールドごとに適用され、用語ごとではないことです(上記の説明 を参照)。

2つ目の問題は関連性に関するもので、first_namelast_name フィールドの異なる用語頻度が予期しない結果を生む可能性があります。

例えば、2人の人がいると想像してみてください。「ウィル・スミス」と「スミス・ジョーンズ」。姓としての「スミス」は非常に一般的で(したがって重要度が低い)、名としての「スミス」は非常に珍しい(したがって重要度が高い)です。

「ウィル・スミス」を検索すると、「スミス・ジョーンズ」ドキュメントが、first_name:smith のスコアが first_name:willlast_name:smith の合計スコアを上回るため、より良い一致の「ウィル・スミス」よりも上に表示される可能性があります。

これらのタイプのクエリに対処する1つの方法は、first_namelast_name フィールドを単一の full_name フィールドにインデックスすることです。もちろん、これはインデックス時にのみ行うことができます。

cross_field タイプは、クエリ時にこれらの問題を解決しようとし、用語中心 のアプローチを取ります。最初にクエリ文字列を個々の用語に分析し、次に各用語を任意のフィールドで探します。まるでそれらが1つの大きなフィールドであるかのように。

次のようなクエリ:

Php

  1. $params = [
  2. 'body' => [
  3. 'query' => [
  4. 'multi_match' => [
  5. 'query' => 'Will Smith',
  6. 'type' => 'cross_fields',
  7. 'fields' => [
  8. 'first_name',
  9. 'last_name',
  10. ],
  11. 'operator' => 'and',
  12. ],
  13. ],
  14. ],
  15. ];
  16. $response = $client->search($params);

Python

  1. resp = client.search(
  2. query={
  3. "multi_match": {
  4. "query": "Will Smith",
  5. "type": "cross_fields",
  6. "fields": [
  7. "first_name",
  8. "last_name"
  9. ],
  10. "operator": "and"
  11. }
  12. },
  13. )
  14. print(resp)

Ruby

  1. response = client.search(
  2. body: {
  3. query: {
  4. multi_match: {
  5. query: 'Will Smith',
  6. type: 'cross_fields',
  7. fields: [
  8. 'first_name',
  9. 'last_name'
  10. ],
  11. operator: 'and'
  12. }
  13. }
  14. }
  15. )
  16. puts response

Go

  1. res, err := es.Search(
  2. es.Search.WithBody(strings.NewReader(`{
  3. "query": {
  4. "multi_match": {
  5. "query": "Will Smith",
  6. "type": "cross_fields",
  7. "fields": [
  8. "first_name",
  9. "last_name"
  10. ],
  11. "operator": "and"
  12. }
  13. }
  14. }`)),
  15. es.Search.WithPretty(),
  16. )
  17. fmt.Println(res, err)

Js

  1. const response = await client.search({
  2. query: {
  3. multi_match: {
  4. query: "Will Smith",
  5. type: "cross_fields",
  6. fields: ["first_name", "last_name"],
  7. operator: "and",
  8. },
  9. },
  10. });
  11. console.log(response);

Console

  1. GET /_search
  2. {
  3. "query": {
  4. "multi_match" : {
  5. "query": "Will Smith",
  6. "type": "cross_fields",
  7. "fields": [ "first_name", "last_name" ],
  8. "operator": "and"
  9. }
  10. }
  11. }

次のように実行されます:

  1. +(first_name:will last_name:will)
  2. +(first_name:smith last_name:smith)

言い換えれば、すべての用語少なくとも1つのフィールド に存在する必要があります。(best_fieldsmost_fields で使用される論理と比較してください。)

これにより、2つの問題のうちの1つが解決されます。異なる用語頻度の問題は、すべてのフィールドの用語頻度をブレンドすることで解決され、違いを均一化します。

実際には、first_name:smithlast_name:smith と同じ頻度を持つかのように扱われ、さらに1が加算されます。これにより、first_namelast_name の一致が比較可能なスコアを持ち、last_name にわずかな利点が与えられます。last_namesmith を含む可能性が最も高いフィールドだからです。

cross_fields は通常、すべての boost1 である短い文字列フィールドでのみ有用です。それ以外の場合、ブースト、用語頻度、長さの正規化がスコアに寄与し、用語統計のブレンドがもはや意味を持たなくなります。

上記のクエリを Validate を通して実行すると、次の説明が返されます:

  1. +blended("will", fields: [first_name, last_name])
  2. +blended("smith", fields: [first_name, last_name])

また、analyzerboostoperatorminimum_should_matchlenientzero_terms_query が受け入れられます。

cross_fields タイプは、フィールド統計を複雑な方法でブレンドし、解釈が難しい場合があります。スコアの組み合わせが不正確になることもあり、特に一部のドキュメントが検索フィールドの一部を含むが、すべてを含まない場合に発生します。combined_fields クエリを代替手段として考慮すべきで、これは用語中心ですが、フィールド統計をより堅牢な方法で組み合わせます。

cross_field and analysis

cross_field タイプは、同じアナライザーを持つフィールドでのみ用語中心モードで機能します。同じアナライザーを持つフィールドは、上記の例のようにグループ化されます。複数のグループがある場合、クエリは任意のグループから最良のスコアを使用します。

例えば、firstlast フィールドが同じアナライザーを持ち、first.edgelast.edgeedge_ngram アナライザーを使用している場合、このクエリ:

Php

  1. $params = [
  2. 'body' => [
  3. 'query' => [
  4. 'multi_match' => [
  5. 'query' => 'Jon',
  6. 'type' => 'cross_fields',
  7. 'fields' => [
  8. 'first',
  9. 'first.edge',
  10. 'last',
  11. 'last.edge',
  12. ],
  13. ],
  14. ],
  15. ],
  16. ];
  17. $response = $client->search($params);

Python

  1. resp = client.search(
  2. query={
  3. "multi_match": {
  4. "query": "Jon",
  5. "type": "cross_fields",
  6. "fields": [
  7. "first",
  8. "first.edge",
  9. "last",
  10. "last.edge"
  11. ]
  12. }
  13. },
  14. )
  15. print(resp)

Ruby

  1. response = client.search(
  2. body: {
  3. query: {
  4. multi_match: {
  5. query: 'Jon',
  6. type: 'cross_fields',
  7. fields: [
  8. 'first',
  9. 'first.edge',
  10. 'last',
  11. 'last.edge'
  12. ]
  13. }
  14. }
  15. }
  16. )
  17. puts response

Go

  1. res, err := es.Search(
  2. es.Search.WithBody(strings.NewReader(`{
  3. "query": {
  4. "multi_match": {
  5. "query": "Jon",
  6. "type": "cross_fields",
  7. "fields": [
  8. "first",
  9. "first.edge",
  10. "last",
  11. "last.edge"
  12. ]
  13. }
  14. }
  15. }`)),
  16. es.Search.WithPretty(),
  17. )
  18. fmt.Println(res, err)

Js

  1. const response = await client.search({
  2. query: {
  3. multi_match: {
  4. query: "Jon",
  5. type: "cross_fields",
  6. fields: ["first", "first.edge", "last", "last.edge"],
  7. },
  8. },
  9. });
  10. console.log(response);

Console

  1. GET /_search
  2. {
  3. "query": {
  4. "multi_match" : {
  5. "query": "Jon",
  6. "type": "cross_fields",
  7. "fields": [
  8. "first", "first.edge",
  9. "last", "last.edge"
  10. ]
  11. }
  12. }
  13. }

次のように実行されます:

  1. blended("jon", fields: [first, last])
  2. | (
  3. blended("j", fields: [first.edge, last.edge])
  4. blended("jo", fields: [first.edge, last.edge])
  5. blended("jon", fields: [first.edge, last.edge])
  6. )

言い換えれば、firstlast はグループ化され、単一のフィールドとして扱われ、first.edgelast.edge はグループ化され、単一のフィールドとして扱われます。

複数のグループを持つことは問題ありませんが、operator または minimum_should_match と組み合わせると、most_fields または best_fields と同じ問題に悩まされる可能性があります。

このクエリを2つの別々の cross_fields クエリとして再構成し、dis_max クエリで組み合わせ、minimum_should_match パラメータをそのうちの1つにのみ適用することができます:

Python

  1. resp = client.search(
  2. query={
  3. "dis_max": {
  4. "queries": [
  5. {
  6. "multi_match": {
  7. "query": "Will Smith",
  8. "type": "cross_fields",
  9. "fields": [
  10. "first",
  11. "last"
  12. ],
  13. "minimum_should_match": "50%"
  14. }
  15. },
  16. {
  17. "multi_match": {
  18. "query": "Will Smith",
  19. "type": "cross_fields",
  20. "fields": [
  21. "*.edge"
  22. ]
  23. }
  24. }
  25. ]
  26. }
  27. },
  28. )
  29. print(resp)

Ruby

  1. response = client.search(
  2. body: {
  3. query: {
  4. dis_max: {
  5. queries: [
  6. {
  7. multi_match: {
  8. query: 'Will Smith',
  9. type: 'cross_fields',
  10. fields: [
  11. 'first',
  12. 'last'
  13. ],
  14. minimum_should_match: '50%'
  15. }
  16. },
  17. {
  18. multi_match: {
  19. query: 'Will Smith',
  20. type: 'cross_fields',
  21. fields: [
  22. '*.edge'
  23. ]
  24. }
  25. }
  26. ]
  27. }
  28. }
  29. }
  30. )
  31. puts response

Js

  1. const response = await client.search({
  2. query: {
  3. dis_max: {
  4. queries: [
  5. {
  6. multi_match: {
  7. query: "Will Smith",
  8. type: "cross_fields",
  9. fields: ["first", "last"],
  10. minimum_should_match: "50%",
  11. },
  12. },
  13. {
  14. multi_match: {
  15. query: "Will Smith",
  16. type: "cross_fields",
  17. fields: ["*.edge"],
  18. },
  19. },
  20. ],
  21. },
  22. },
  23. });
  24. console.log(response);

Console

  1. GET /_search
  2. {
  3. "query": {
  4. "dis_max": {
  5. "queries": [
  6. {
  7. "multi_match" : {
  8. "query": "Will Smith",
  9. "type": "cross_fields",
  10. "fields": [ "first", "last" ],
  11. "minimum_should_match": "50%"
  12. }
  13. },
  14. {
  15. "multi_match" : {
  16. "query": "Will Smith",
  17. "type": "cross_fields",
  18. "fields": [ "*.edge" ]
  19. }
  20. }
  21. ]
  22. }
  23. }
  24. }
will または smith は、first または last フィールドのいずれかに存在する必要があります。

クエリ内で analyzer パラメータを指定することで、すべてのフィールドを同じグループに強制することができます。

Php

  1. $params = [
  2. 'body' => [
  3. 'query' => [
  4. 'multi_match' => [
  5. 'query' => 'Jon',
  6. 'type' => 'cross_fields',
  7. 'analyzer' => 'standard',
  8. 'fields' => [
  9. 'first',
  10. 'last',
  11. '*.edge',
  12. ],
  13. ],
  14. ],
  15. ],
  16. ];
  17. $response = $client->search($params);

Python

  1. resp = client.search(
  2. query={
  3. "multi_match": {
  4. "query": "Jon",
  5. "type": "cross_fields",
  6. "analyzer": "standard",
  7. "fields": [
  8. "first",
  9. "last",
  10. "*.edge"
  11. ]
  12. }
  13. },
  14. )
  15. print(resp)

Ruby

  1. response = client.search(
  2. body: {
  3. query: {
  4. multi_match: {
  5. query: 'Jon',
  6. type: 'cross_fields',
  7. analyzer: 'standard',
  8. fields: [
  9. 'first',
  10. 'last',
  11. '*.edge'
  12. ]
  13. }
  14. }
  15. }
  16. )
  17. puts response

Go

  1. res, err := es.Search(
  2. es.Search.WithBody(strings.NewReader(`{
  3. "query": {
  4. "multi_match": {
  5. "query": "Jon",
  6. "type": "cross_fields",
  7. "analyzer": "standard",
  8. "fields": [
  9. "first",
  10. "last",
  11. "*.edge"
  12. ]
  13. }
  14. }
  15. }`)),
  16. es.Search.WithPretty(),
  17. )
  18. fmt.Println(res, err)

Js

  1. const response = await client.search({
  2. query: {
  3. multi_match: {
  4. query: "Jon",
  5. type: "cross_fields",
  6. analyzer: "standard",
  7. fields: ["first", "last", "*.edge"],
  8. },
  9. },
  10. });
  11. console.log(response);

Console

  1. GET /_search
  2. {
  3. "query": {
  4. "multi_match" : {
  5. "query": "Jon",
  6. "type": "cross_fields",
  7. "analyzer": "standard",
  8. "fields": [ "first", "last", "*.edge" ]
  9. }
  10. }
  11. }
すべてのフィールドに standard アナライザーを使用します。

次のように実行されます:

  1. blended("will", fields: [first, first.edge, last.edge, last])
  2. blended("smith", fields: [first, first.edge, last.edge, last])

tie_breaker

デフォルトでは、各用語ごとの blended クエリは、グループ内の任意のフィールドから返された最良のスコアを使用します。次に、グループ間でスコアを組み合わせると、クエリは任意のグループからの最良のスコアを使用します。tie_breaker パラメータは、これらのステップの両方の動作を変更できます:

0.0 (例)first_name:willlast_name:will の中から単一の最良スコアを取得します(デフォルト)
1.0 (例)first_name:willlast_name:will のスコアを合計します
0.0 < n < 1.0 単一の最良スコアに tie_breaker を掛けたものを、他の一致フィールド/グループからの各スコアに加えます

cross_fields and fuzziness

fuzziness パラメータは、cross_fields タイプと一緒に使用できません。

bool_prefix

bool_prefix タイプのスコアリングは、most_fields のように動作しますが、match クエリの代わりに match_bool_prefix クエリ を使用します。

Php

  1. $params = [
  2. 'body' => [
  3. 'query' => [
  4. 'multi_match' => [
  5. 'query' => 'quick brown f',
  6. 'type' => 'bool_prefix',
  7. 'fields' => [
  8. 'subject',
  9. 'message',
  10. ],
  11. ],
  12. ],
  13. ],
  14. ];
  15. $response = $client->search($params);

Python

  1. resp = client.search(
  2. query={
  3. "multi_match": {
  4. "query": "quick brown f",
  5. "type": "bool_prefix",
  6. "fields": [
  7. "subject",
  8. "message"
  9. ]
  10. }
  11. },
  12. )
  13. print(resp)

Ruby

  1. response = client.search(
  2. body: {
  3. query: {
  4. multi_match: {
  5. query: 'quick brown f',
  6. type: 'bool_prefix',
  7. fields: [
  8. 'subject',
  9. 'message'
  10. ]
  11. }
  12. }
  13. }
  14. )
  15. puts response

Go

  1. res, err := es.Search(
  2. es.Search.WithBody(strings.NewReader(`{
  3. "query": {
  4. "multi_match": {
  5. "query": "quick brown f",
  6. "type": "bool_prefix",
  7. "fields": [
  8. "subject",
  9. "message"
  10. ]
  11. }
  12. }
  13. }`)),
  14. es.Search.WithPretty(),
  15. )
  16. fmt.Println(res, err)

Js

  1. const response = await client.search({
  2. query: {
  3. multi_match: {
  4. query: "quick brown f",
  5. type: "bool_prefix",
  6. fields: ["subject", "message"],
  7. },
  8. },
  9. });
  10. console.log(response);

Console

  1. GET /_search
  2. {
  3. "query": {
  4. "multi_match" : {
  5. "query": "quick brown f",
  6. "type": "bool_prefix",
  7. "fields": [ "subject", "message" ]
  8. }
  9. }
  10. }

analyzer 、[boost] 、[operator] 、[minimum_should_match] 、[lenient] 、[zero_terms_query] 、[auto_generate_synonyms_phrase_query] パラメータは、match query で説明されているようにサポートされています。[fuzziness] 、[prefix_length] 、[max_expansions] 、[fuzzy_rewrite] 、[fuzzy_transpositions] パラメータは、用語クエリを構築するために使用される用語に対してサポートされていますが、最終的な用語から構築されたプレフィックスクエリには影響しません。

slop パラメータは、このクエリタイプではサポートされていません。