検索アプリケーションの検索APIとテンプレート

あなたの検索アプリケーションは、検索テンプレートを使用して検索を実行します。テンプレートは、テンプレートパラメータのみを公開することで複雑さを軽減し、ElasticsearchのクエリDSLの全機能を使用してクエリを構築します。テンプレートは、検索アプリケーションを作成または更新する際に設定でき、カスタマイズ可能です。このテンプレートは、Put Search Application API APIコールを使用して、いつでも編集または更新できます。

要するに、特定のハードコーディングされた検索値の代わりにパラメータを使用して検索テンプレートを作成します。検索時には、これらのパラメータの実際の値を渡すことで、クエリ全体の構造を書き換えることなくカスタマイズされた検索を可能にします。検索アプリケーションテンプレート:

  • クエリリクエストを簡素化
  • リクエストサイズを削減
  • クエリが事前定義されており、恣意的に変更できないため、セキュリティとパフォーマンスを確保

この文書は、追加のユースケースで検索アプリケーションを使用するための情報とサンプルテンプレートを提供します。これらのテンプレートは、ニーズに合わせて簡単に変更できるように設計されています。テンプレートを使用して検索アプリケーションを作成したら、このテンプレートを使用して検索アプリケーションを検索できます。

検索テンプレートは、Mustacheテンプレート言語を使用します。Mustache変数は通常、次のように二重波括弧で囲まれます: {{my-var}}.

検索テンプレートについての詳細を学びましょう。

デフォルトテンプレートの例

検索アプリケーションにテンプレートが保存されていない場合、最小限のデフォルト検索テンプレートが検索時に適用されます。デフォルトテンプレートは、シンプルな検索ユースケースを実装します。

デフォルトテンプレートで検索アプリケーションを作成するには、テンプレートを指定せずに検索アプリケーションの作成または更新リクエストを発行します:

Python

  1. resp = client.search_application.put(
  2. name="my_search_application",
  3. search_application={
  4. "indices": [
  5. "index1",
  6. "index2"
  7. ]
  8. },
  9. )
  10. print(resp)

Js

  1. const response = await client.searchApplication.put({
  2. name: "my_search_application",
  3. search_application: {
  4. indices: ["index1", "index2"],
  5. },
  6. });
  7. console.log(response);

コンソール

  1. PUT _application/search_application/my_search_application
  2. {
  3. "indices": ["index1", "index2"]
  4. }

次に、get search application APIコールを使用して、新しく作成した検索アプリケーションを表示できます。これには、あなたのために作成されたデフォルトテンプレートも含まれます:

Python

  1. resp = client.search_application.get(
  2. name="my_search_application",
  3. )
  4. print(resp)

Js

  1. const response = await client.searchApplication.get({
  2. name: "my_search_application",
  3. });
  4. console.log(response);

コンソール

  1. GET _application/search_application/my_search_application

この場合、応答は次のようになります:

コンソール-結果

  1. {
  2. "name": "my_search_application",
  3. "indices": [
  4. "index1",
  5. "index2"
  6. ],
  7. "updated_at_millis": 1715802354482,
  8. "template": {
  9. "script": {
  10. "source": """{
  11. "query": {
  12. "query_string": {
  13. "query": "{{query_string}}",
  14. "default_field": "{{default_field}}"
  15. }
  16. }
  17. }
  18. """,
  19. "lang": "mustache",
  20. "params": {
  21. "default_field": "*",
  22. "query_string": "*"
  23. }
  24. }
  25. }
  26. }

デフォルトテンプレートは非常に最小限です:

コンソール-結果

  1. {
  2. "template": {
  3. "script": {
  4. "source": {
  5. "query": {
  6. "query_string": {
  7. "query": "{{query_string}}",
  8. "default_field": "{{default_field}}"
  9. }
  10. }
  11. },
  12. "params": {
  13. "query_string": "*",
  14. "default_field": "*"
  15. }
  16. }
  17. }
  18. }

これは、検索テンプレートの初期探索に役立つかもしれませんが、更新したいと思うでしょう。

このテンプレートは、fromsize、またはboostを含む追加のパラメータをサポートしていません。これらを使用する必要がある場合は、検索アプリケーションに関連付けられたテンプレートをカスタマイズして、パラメータとして含めることができます。

テンプレートを表示することで、パラメータとそのデフォルト値を確認できますが、さまざまなパラメータで検索アプリケーションを検索した場合に生成されるクエリを表示することも価値があります。

render search application queryを使用して、このテンプレートが生成するクエリを表示できます。デフォルトパラメータを含む場合もあります。たとえば、パラメータなしで検索アプリケーションを検索すると:

Python

  1. resp = client.search_application.render_query(
  2. name="my_search_application",
  3. body=None,
  4. )
  5. print(resp)

Js

  1. const response = await client.searchApplication.renderQuery({
  2. name: "my_search_application",
  3. body: null,
  4. });
  5. console.log(response);

コンソール

  1. POST _application/search_application/my_search_application/_render_query

次のように返されます:

コンソール-結果

  1. {
  2. "query": {
  3. "query_string": {
  4. "query": "*",
  5. "default_field": "*",
  6. "fields": []
  7. }
  8. }
  9. }

これは、テンプレートで定義されたデフォルトパラメータを使用しています。レンダリングコールに1つ以上のパラメータを指定することもできます。たとえば:

Python

  1. resp = client.search_application.render_query(
  2. name="my_search_application",
  3. body={
  4. "params": {
  5. "query_string": "rock climbing"
  6. }
  7. },
  8. )
  9. print(resp)

Js

  1. const response = await client.searchApplication.renderQuery({
  2. name: "my_search_application",
  3. body: {
  4. params: {
  5. query_string: "rock climbing",
  6. },
  7. },
  8. });
  9. console.log(response);

コンソール

  1. POST _application/search_application/my_search_application/_render_query
  2. {
  3. "params": {
  4. "query_string": "rock climbing"
  5. }
  6. }

次のように返されます:

コンソール-結果

  1. {
  2. "query": {
  3. "query_string": {
  4. "query": "rock climbing",
  5. "default_field": "*",
  6. "fields": []
  7. }
  8. }
  9. }

この場合、{{query_string}}パラメータはrock climbingの値に置き換えられ、{{default_field}}パラメータは指定されていないため、*のデフォルト値が使用されます。

実際にパラメータなしで検索を実行すると、レンダリングコールが返した基礎となるクエリが実行されます。この場合、パラメータなしの検索はすべての結果を返し、/_searchへのパラメータなしの呼び出しと同様の方法で行われます。

Python

  1. resp = client.search_application.search(
  2. name="my_search_application",
  3. )
  4. print(resp)

Js

  1. const response = await client.searchApplication.search({
  2. name: "my_search_application",
  3. });
  4. console.log(response);

コンソール

  1. POST _application/search_application/my_search_application/_search
  1. デフォルトテンプレートは、今後の検索アプリケーション機能のバージョンで変更される可能性があります。
  2. この文書の他の例を試して、特定のユースケースを実験するか、自分自身のものを作成してみてください!
  3. ## 検索アプリケーションの検索
  4. ### テンプレート検索
  5. 検索アプリケーションと対話する最も簡単な方法は、それに関連付けられた検索テンプレートを使用することです。各検索アプリケーションには、検索基準、パラメータ、およびデフォルトを定義する単一のテンプレートが関連付けられています。
  6. [Search Application Search API](/read/elasticsearch-8-15/e5fa8e999386c615.md)を使用して、検索アプリケーションに検索リクエストを送信します。
  7. デフォルトテンプレートを使用すると、検索は次のようになります:
  8. #### Python
  9. ``````python
  10. resp = client.search_application.search(
  11. name="my_search_application",
  12. params={
  13. "query_string": "kayaking"
  14. },
  15. )
  16. print(resp)
  17. `

Js

  1. const response = await client.searchApplication.search({
  2. name: "my_search_application",
  3. params: {
  4. query_string: "kayaking",
  5. },
  6. });
  7. console.log(response);

コンソール

  1. POST _application/search_application/my_search_application/_search
  2. {
  3. "params": {
  4. "query_string": "kayaking"
  5. }
  6. }

この例では、query_stringパラメータのデフォルト値*をオーバーライドしました。default_fieldを指定しなかったため、このパラメータの値は*のままです。

エイリアス検索

検索アプリケーションの検索テンプレートを設定したくない場合、検索アプリケーションと同じ名前のエイリアスが作成されます。これは、検索アプリケーションの検索テンプレートを構築する際に使用したい特定の検索クエリを実験する際に役立ちます。

検索アプリケーションの名前がmy_search_applicationの場合、エイリアスはmy_search_applicationになります。これをsearch APIを使用して検索できます。

クロスクラスタ検索

検索アプリケーションは現在、クロスクラスタ検索をサポートしていません。リモートクラスタのインデックスやインデックスパターンをインデックスエイリアスに追加することはできません。

検索アプリケーションを更新するには、Search Applications管理APIを使用し、エイリアスAPIなどのElasticsearch APIを直接使用しないでください。たとえば、indicesパラメータを使用してPUT Search Applicationを使用します。これにより、関連付けられたエイリアスが自動的に最新の状態に保たれ、インデックスが検索アプリケーションに正しく追加されることが保証されます。

検索テンプレートの例

特定のユースケースを探求するために、いくつかの例を作成しました。これらを自分の検索テンプレートを作成するための出発点として使用してください。

テキスト検索の例

次のテンプレートは、指定されたフィールドに対するmulti_match検索とブーストをサポートします:

Python

  1. resp = client.search_application.put(
  2. name="my_search_application",
  3. search_application={
  4. "indices": [
  5. "index1",
  6. "index2"
  7. ],
  8. "template": {
  9. "script": {
  10. "lang": "mustache",
  11. "source": "\n {\n \"query\": {\n \"multi_match\": {\n \"query\": \"{{query_string}}\",\n \"fields\": [{{#text_fields}}\"{{name}}^{{boost}}\",{{/text_fields}}]\n }\n },\n \"explain\": \"{{explain}}\",\n \"from\": \"{{from}}\",\n \"size\": \"{{size}}\"\n }\n ",
  12. "params": {
  13. "query_string": "*",
  14. "text_fields": [
  15. {
  16. "name": "title",
  17. "boost": 10
  18. },
  19. {
  20. "name": "description",
  21. "boost": 5
  22. }
  23. ],
  24. "explain": False,
  25. "from": 0,
  26. "size": 10
  27. }
  28. }
  29. }
  30. },
  31. )
  32. print(resp)

Js

  1. const response = await client.searchApplication.put({
  2. name: "my_search_application",
  3. search_application: {
  4. indices: ["index1", "index2"],
  5. template: {
  6. script: {
  7. lang: "mustache",
  8. source:
  9. '\n {\n "query": {\n "multi_match": {\n "query": "{{query_string}}",\n "fields": [{{#text_fields}}"{{name}}^{{boost}}",{{/text_fields}}]\n }\n },\n "explain": "{{explain}}",\n "from": "{{from}}",\n "size": "{{size}}"\n }\n ',
  10. params: {
  11. query_string: "*",
  12. text_fields: [
  13. {
  14. name: "title",
  15. boost: 10,
  16. },
  17. {
  18. name: "description",
  19. boost: 5,
  20. },
  21. ],
  22. explain: false,
  23. from: 0,
  24. size: 10,
  25. },
  26. },
  27. },
  28. },
  29. });
  30. console.log(response);

コンソール

  1. PUT _application/search_application/my_search_application
  2. {
  3. "indices": ["index1", "index2"],
  4. "template": {
  5. "script": {
  6. "lang": "mustache",
  7. "source": """
  8. {
  9. "query": {
  10. "multi_match": {
  11. "query": "{{query_string}}",
  12. "fields": [{{#text_fields}}"{{name}}^{{boost}}",{{/text_fields}}]
  13. }
  14. },
  15. "explain": "{{explain}}",
  16. "from": "{{from}}",
  17. "size": "{{size}}"
  18. }
  19. """,
  20. "params": {
  21. "query_string": "*",
  22. "text_fields": [
  23. {"name": "title", "boost": 10},
  24. {"name": "description", "boost": 5}
  25. ],
  26. "explain": false,
  27. "from": 0,
  28. "size": 10
  29. }
  30. }
  31. }
  32. }

このテンプレートを使用した検索クエリは次のようになります:

Python

  1. resp = client.search_application.search(
  2. name="my_search_application",
  3. params={
  4. "size": 5,
  5. "query_string": "mountain climbing",
  6. "text_fields": [
  7. {
  8. "name": "title",
  9. "boost": 10
  10. },
  11. {
  12. "name": "description",
  13. "boost": 2
  14. },
  15. {
  16. "name": "state",
  17. "boost": 1
  18. }
  19. ]
  20. },
  21. )
  22. print(resp)

Js

  1. const response = await client.searchApplication.search({
  2. name: "my_search_application",
  3. params: {
  4. size: 5,
  5. query_string: "mountain climbing",
  6. text_fields: [
  7. {
  8. name: "title",
  9. boost: 10,
  10. },
  11. {
  12. name: "description",
  13. boost: 2,
  14. },
  15. {
  16. name: "state",
  17. boost: 1,
  18. },
  19. ],
  20. },
  21. });
  22. console.log(response);

コンソール

  1. POST _application/search_application/my_search_application/_search
  2. {
  3. "params": {
  4. "size": 5,
  5. "query_string": "mountain climbing",
  6. "text_fields": [
  7. {"name": "title", "boost": 10},
  8. {"name": "description", "boost": 2},
  9. {"name": "state", "boost": 1}
  10. ]
  11. }
  12. }
  1. ### テキスト検索 + ELSERとRRF
  2. この例は、BM25と[ELSER](https://www.elastic.co/guide/en/machine-learning/8.15/ml-nlp-elser.html)検索を組み合わせるための[逆順位融合 (RRF)](/read/elasticsearch-8-15/6f3c8b9c492b896d.md)メソッドをサポートします。逆順位融合は、異なる検索アルゴリズムの組み合わせ結果を一貫して改善します。他のすべてのランキングアルゴリズムを上回り、しばしば最良の個別結果を超え、キャリブレーションなしで実現します。
  3. #### Python
  4. ``````python
  5. resp = client.search_application.put(
  6. name="my-search-app",
  7. search_application={
  8. "indices": [
  9. "index1"
  10. ],
  11. "template": {
  12. "script": {
  13. "lang": "mustache",
  14. "source": "\n {\n \"retriever\": {\n \"rrf\": {\n \"retrievers\": [\n {{#text_fields}}\n {\n \"standard\": {\n \"query\": {\n \"match\": {\n \"{{.}}\": \"{{query_string}}\"\n }\n }\n }\n },\n {{/text_fields}}\n {{#elser_fields}}\n {\n \"standard\": {\n \"query\": {\n \"sparse_vector\": {\n \"field\": \"ml.inference.{{.}}_expanded.predicted_value\",\n \"inference_id\": \"<elser_inference_id>\",\n \"query\": \"{{query_string}}\"\n }\n }\n }\n },\n {{/elser_fields}}\n ],\n \"rank_window_size\": {{rrf.rank_window_size}},\n \"rank_constant\": {{rrf.rank_constant}}\n }\n }\n }\n ",
  15. "params": {
  16. "elser_fields": [
  17. "title",
  18. "meta_description"
  19. ],
  20. "text_fields": [
  21. "title",
  22. "meta_description"
  23. ],
  24. "query_string": "",
  25. "rrf": {
  26. "rank_window_size": 100,
  27. "rank_constant": 60
  28. }
  29. }
  30. }
  31. }
  32. },
  33. )
  34. print(resp)
  35. `

Js

  1. const response = await client.searchApplication.put({
  2. name: "my-search-app",
  3. search_application: {
  4. indices: ["index1"],
  5. template: {
  6. script: {
  7. lang: "mustache",
  8. source:
  9. '\n {\n "retriever": {\n "rrf": {\n "retrievers": [\n {{#text_fields}}\n {\n "standard": {\n "query": {\n "match": {\n "{{.}}": "{{query_string}}"\n }\n }\n }\n },\n {{/text_fields}}\n {{#elser_fields}}\n {\n "standard": {\n "query": {\n "sparse_vector": {\n "field": "ml.inference.{{.}}_expanded.predicted_value",\n "inference_id": "<elser_inference_id>",\n "query": "{{query_string}}"\n }\n }\n }\n },\n {{/elser_fields}}\n ],\n "rank_window_size": {{rrf.rank_window_size}},\n "rank_constant": {{rrf.rank_constant}}\n }\n }\n }\n ',
  10. params: {
  11. elser_fields: ["title", "meta_description"],
  12. text_fields: ["title", "meta_description"],
  13. query_string: "",
  14. rrf: {
  15. rank_window_size: 100,
  16. rank_constant: 60,
  17. },
  18. },
  19. },
  20. },
  21. },
  22. });
  23. console.log(response);

コンソール

  1. PUT _application/search_application/my-search-app
  2. {
  3. "indices": [
  4. "index1"
  5. ],
  6. "template": {
  7. "script": {
  8. "lang": "mustache",
  9. "source": """
  10. {
  11. "retriever": {
  12. "rrf": {
  13. "retrievers": [
  14. {{#text_fields}}
  15. {
  16. "standard": {
  17. "query": {
  18. "match": {
  19. "{{.}}": "{{query_string}}"
  20. }
  21. }
  22. }
  23. },
  24. {{/text_fields}}
  25. {{#elser_fields}}
  26. {
  27. "standard": {
  28. "query": {
  29. "sparse_vector": {
  30. "field": "ml.inference.{{.}}_expanded.predicted_value",
  31. "inference_id": "<elser_inference_id>",
  32. "query": "{{query_string}}"
  33. }
  34. }
  35. }
  36. },
  37. {{/elser_fields}}
  38. ],
  39. "rank_window_size": {{rrf.rank_window_size}},
  40. "rank_constant": {{rrf.rank_constant}}
  41. }
  42. }
  43. }
  44. """,
  45. "params": {
  46. "elser_fields": ["title", "meta_description"],
  47. "text_fields": ["title", "meta_description"],
  48. "query_string": "",
  49. "rrf": {
  50. "rank_window_size": 100,
  51. "rank_constant": 60
  52. }
  53. }
  54. }
  55. }
  56. }
  1. このテンプレートのサンプルクエリは次のようになります:
  2. #### Python
  3. ``````python
  4. resp = client.search_application.search(
  5. name="my-search-app",
  6. params={
  7. "query_string": "What is the most popular brand of coffee sold in the United States?",
  8. "elser_fields": [
  9. "title",
  10. "meta_description"
  11. ],
  12. "text_fields": [
  13. "title",
  14. "meta_description"
  15. ],
  16. "rrf": {
  17. "rank_window_size": 50,
  18. "rank_constant": 25
  19. }
  20. },
  21. )
  22. print(resp)
  23. `

Js

  1. const response = await client.searchApplication.search({
  2. name: "my-search-app",
  3. params: {
  4. query_string:
  5. "What is the most popular brand of coffee sold in the United States?",
  6. elser_fields: ["title", "meta_description"],
  7. text_fields: ["title", "meta_description"],
  8. rrf: {
  9. rank_window_size: 50,
  10. rank_constant: 25,
  11. },
  12. },
  13. });
  14. console.log(response);

コンソール

  1. POST _application/search_application/my-search-app/_search
  2. {
  3. "params": {
  4. "query_string": "What is the most popular brand of coffee sold in the United States?",
  5. "elser_fields": ["title", "meta_description"],
  6. "text_fields": ["title", "meta_description"],
  7. "rrf": {
  8. "rank_window_size": 50,
  9. "rank_constant": 25
  10. }
  11. }
  12. }

テキスト検索 + ELSER

Elastic Learned Sparse EncodeR (ELSER)は、テキスト拡張を通じて検索の関連性を向上させ、意味的検索を可能にします。この実験的テンプレートは、1つ以上のフィールドでELSERを有効にする必要があります。ELSERを使用した意味的検索を参照して、ELSERの使用方法についての詳細を確認してください。この場合、ELSERはtitleおよびdescriptionフィールドで有効になっています。

この例は、さまざまな検索アプリケーションシナリオで使用できる単一のテンプレートを提供します: テキスト検索、ELSER、またはその両方。パラメータが指定されていない場合は、シンプルなデフォルトquery_stringクエリも提供します。

Python

  1. resp = client.search_application.put(
  2. name="my_search_application",
  3. search_application={
  4. "indices": [
  5. "index1",
  6. "index2"
  7. ],
  8. "template": {
  9. "script": {
  10. "lang": "mustache",
  11. "source": "\n {\n \"query\": {\n \"bool\": {\n \"should\": [\n {{#text}}\n {\n \"multi_match\": {\n \"query\": \"{{query_string}}\",\n \"fields\": [{{#text_fields}}\"{{name}}^{{boost}}\",{{/text_fields}}],\n \"boost\": \"{{text_query_boost}}\"\n }\n },\n {{/text}}\n {{#elser}}\n {{#elser_fields}}\n {\n \"sparse_vector\": {\n \"field\": \"ml.inference.{{.}}_expanded.predicted_value\",\n \"inference_id\": \"<elser_inference_id>\",\n \"query\": \"{{query_string}}\"\n }\n },\n {{/elser_fields}}\n { \"bool\": { \"must\": [] } },\n {{/elser}}\n {{^text}}\n {{^elser}}\n {\n \"query_string\": {\n \"query\": \"{{query_string}}\",\n \"default_field\": \"{{default_field}}\",\n \"default_operator\": \"{{default_operator}}\",\n \"boost\": \"{{text_query_boost}}\"\n }\n },\n {{/elser}}\n {{/text}}\n { \"bool\": { \"must\": [] } }\n ],\n \"minimum_should_match\": 1\n }\n },\n \"min_score\": \"{{min_score}}\",\n \"explain\": \"{{explain}}\",\n \"from\": \"{{from}}\",\n \"size\": \"{{size}}\"\n }\n ",
  12. "params": {
  13. "text": False,
  14. "elser": False,
  15. "elser_fields": [
  16. {
  17. "name": "title",
  18. "boost": 1
  19. },
  20. {
  21. "name": "description",
  22. "boost": 1
  23. }
  24. ],
  25. "text_fields": [
  26. {
  27. "name": "title",
  28. "boost": 10
  29. },
  30. {
  31. "name": "description",
  32. "boost": 5
  33. },
  34. {
  35. "name": "state",
  36. "boost": 1
  37. }
  38. ],
  39. "query_string": "*",
  40. "text_query_boost": 4,
  41. "default_field": "*",
  42. "default_operator": "OR",
  43. "explain": False,
  44. "from": 0,
  45. "size": 10,
  46. "min_score": 0
  47. }
  48. }
  49. }
  50. },
  51. )
  52. print(resp)

Js

  1. const response = await client.searchApplication.put({
  2. name: "my_search_application",
  3. search_application: {
  4. indices: ["index1", "index2"],
  5. template: {
  6. script: {
  7. lang: "mustache",
  8. source:
  9. '\n {\n "query": {\n "bool": {\n "should": [\n {{#text}}\n {\n "multi_match": {\n "query": "{{query_string}}",\n "fields": [{{#text_fields}}"{{name}}^{{boost}}",{{/text_fields}}],\n "boost": "{{text_query_boost}}"\n }\n },\n {{/text}}\n {{#elser}}\n {{#elser_fields}}\n {\n "sparse_vector": {\n "field": "ml.inference.{{.}}_expanded.predicted_value",\n "inference_id": "<elser_inference_id>",\n "query": "{{query_string}}"\n }\n },\n {{/elser_fields}}\n { "bool": { "must": [] } },\n {{/elser}}\n {{^text}}\n {{^elser}}\n {\n "query_string": {\n "query": "{{query_string}}",\n "default_field": "{{default_field}}",\n "default_operator": "{{default_operator}}",\n "boost": "{{text_query_boost}}"\n }\n },\n {{/elser}}\n {{/text}}\n { "bool": { "must": [] } }\n ],\n "minimum_should_match": 1\n }\n },\n "min_score": "{{min_score}}",\n "explain": "{{explain}}",\n "from": "{{from}}",\n "size": "{{size}}"\n }\n ',
  10. params: {
  11. text: false,
  12. elser: false,
  13. elser_fields: [
  14. {
  15. name: "title",
  16. boost: 1,
  17. },
  18. {
  19. name: "description",
  20. boost: 1,
  21. },
  22. ],
  23. text_fields: [
  24. {
  25. name: "title",
  26. boost: 10,
  27. },
  28. {
  29. name: "description",
  30. boost: 5,
  31. },
  32. {
  33. name: "state",
  34. boost: 1,
  35. },
  36. ],
  37. query_string: "*",
  38. text_query_boost: 4,
  39. default_field: "*",
  40. default_operator: "OR",
  41. explain: false,
  42. from: 0,
  43. size: 10,
  44. min_score: 0,
  45. },
  46. },
  47. },
  48. },
  49. });
  50. console.log(response);

コンソール

  1. PUT _application/search_application/my_search_application
  2. {
  3. "indices": [
  4. "index1",
  5. "index2"
  6. ],
  7. "template": {
  8. "script": {
  9. "lang": "mustache",
  10. "source": """
  11. {
  12. "query": {
  13. "bool": {
  14. "should": [
  15. {{#text}}
  16. {
  17. "multi_match": {
  18. "query": "{{query_string}}",
  19. "fields": [{{#text_fields}}"{{name}}^{{boost}}",{{/text_fields}}],
  20. "boost": "{{text_query_boost}}"
  21. }
  22. },
  23. {{/text}}
  24. {{#elser}}
  25. {{#elser_fields}}
  26. {
  27. "sparse_vector": {
  28. "field": "ml.inference.{{.}}_expanded.predicted_value",
  29. "inference_id": "<elser_inference_id>",
  30. "query": "{{query_string}}"
  31. }
  32. },
  33. {{/elser_fields}}
  34. { "bool": { "must": [] } },
  35. {{/elser}}
  36. {{^text}}
  37. {{^elser}}
  38. {
  39. "query_string": {
  40. "query": "{{query_string}}",
  41. "default_field": "{{default_field}}",
  42. "default_operator": "{{default_operator}}",
  43. "boost": "{{text_query_boost}}"
  44. }
  45. },
  46. {{/elser}}
  47. {{/text}}
  48. { "bool": { "must": [] } }
  49. ],
  50. "minimum_should_match": 1
  51. }
  52. },
  53. "min_score": "{{min_score}}",
  54. "explain": "{{explain}}",
  55. "from": "{{from}}",
  56. "size": "{{size}}"
  57. }
  58. """,
  59. "params": {
  60. "text": false,
  61. "elser": false,
  62. "elser_fields": [
  63. {"name": "title", "boost": 1},
  64. {"name": "description", "boost": 1}
  65. ],
  66. "text_fields": [
  67. {"name": "title", "boost": 10},
  68. {"name": "description", "boost": 5},
  69. {"name": "state", "boost": 1}
  70. ],
  71. "query_string": "*",
  72. "text_query_boost": 4,
  73. "default_field": "*",
  74. "default_operator": "OR",
  75. "explain": false,
  76. "from": 0,
  77. "size": 10,
  78. "min_score": 0
  79. }
  80. }
  81. }
  82. }

このテンプレートを使用したテキスト検索クエリは次のようになります:

Python

  1. resp = client.search_application.search(
  2. name="my_search_application",
  3. params={
  4. "text": True,
  5. "size": 5,
  6. "query_string": "mountain climbing",
  7. "text_fields": [
  8. {
  9. "name": "title",
  10. "boost": 10
  11. },
  12. {
  13. "name": "description",
  14. "boost": 5
  15. },
  16. {
  17. "name": "state",
  18. "boost": 1
  19. }
  20. ]
  21. },
  22. )
  23. print(resp)

Js

  1. const response = await client.searchApplication.search({
  2. name: "my_search_application",
  3. params: {
  4. text: true,
  5. size: 5,
  6. query_string: "mountain climbing",
  7. text_fields: [
  8. {
  9. name: "title",
  10. boost: 10,
  11. },
  12. {
  13. name: "description",
  14. boost: 5,
  15. },
  16. {
  17. name: "state",
  18. boost: 1,
  19. },
  20. ],
  21. },
  22. });
  23. console.log(response);

コンソール

  1. POST _application/search_application/my_search_application/_search
  2. {
  3. "params": {
  4. "text": true,
  5. "size": 5,
  6. "query_string": "mountain climbing",
  7. "text_fields": [
  8. {"name": "title", "boost": 10},
  9. {"name": "description", "boost": 5},
  10. {"name": "state", "boost": 1}
  11. ]
  12. }
  13. }

このテンプレートを使用したELSER検索クエリは次のようになります:

Python

  1. resp = client.search_application.search(
  2. name="my_search_application",
  3. params={
  4. "elser": True,
  5. "query_string": "where is the best mountain climbing?",
  6. "elser_fields": [
  7. {
  8. "name": "title",
  9. "boost": 1
  10. },
  11. {
  12. "name": "description",
  13. "boost": 1
  14. }
  15. ]
  16. },
  17. )
  18. print(resp)

Js

  1. const response = await client.searchApplication.search({
  2. name: "my_search_application",
  3. params: {
  4. elser: true,
  5. query_string: "where is the best mountain climbing?",
  6. elser_fields: [
  7. {
  8. name: "title",
  9. boost: 1,
  10. },
  11. {
  12. name: "description",
  13. boost: 1,
  14. },
  15. ],
  16. },
  17. });
  18. console.log(response);

コンソール

  1. POST _application/search_application/my_search_application/_search
  2. {
  3. "params": {
  4. "elser": true,
  5. "query_string": "where is the best mountain climbing?",
  6. "elser_fields": [
  7. {"name": "title", "boost": 1},
  8. {"name": "description", "boost": 1}
  9. ]
  10. }
  11. }

このテンプレートを使用したテキスト検索とELSER検索の組み合わせクエリは次のようになります:

Python

  1. resp = client.search_application.search(
  2. name="my_search_application",
  3. params={
  4. "elser": True,
  5. "text": True,
  6. "query_string": "where is the best mountain climbing?",
  7. "elser_fields": [
  8. {
  9. "name": "title",
  10. "boost": 1
  11. },
  12. {
  13. "name": "description",
  14. "boost": 1
  15. }
  16. ],
  17. "text_query_boost": 4,
  18. "min_score": 10
  19. },
  20. )
  21. print(resp)

Js

  1. const response = await client.searchApplication.search({
  2. name: "my_search_application",
  3. params: {
  4. elser: true,
  5. text: true,
  6. query_string: "where is the best mountain climbing?",
  7. elser_fields: [
  8. {
  9. name: "title",
  10. boost: 1,
  11. },
  12. {
  13. name: "description",
  14. boost: 1,
  15. },
  16. ],
  17. text_query_boost: 4,
  18. min_score: 10,
  19. },
  20. });
  21. console.log(response);

コンソール

  1. POST _application/search_application/my_search_application/_search
  2. {
  3. "params": {
  4. "elser": true,
  5. "text": true,
  6. "query_string": "where is the best mountain climbing?",
  7. "elser_fields": [
  8. {"name": "title", "boost": 1},
  9. {"name": "description", "boost": 1}
  10. ],
  11. "text_query_boost": 4,
  12. "min_score": 10
  13. }
  14. }

テキスト検索結果とELSER検索結果は、場合によっては大きく異なるスコアを持つことが予想され、ランキングが難しくなります。データセットに最適な検索結果のミックスを見つけるために、例のテンプレートで提供されるブースト値を使って実験することをお勧めします:

  • BM25クエリ全体をブーストするためのtext_query_boost
  • 個々のテキスト検索フィールドをブーストするためのboostフィールド
  • 重要度の低い結果を省くためのmin_scoreパラメータ

上記のブーストは、多くのユースケースに対して十分であるはずですが、テンプレートに再スコアクエリやインデックスブーストを追加することが有益な場合もあります。新しいテンプレートを使用するために検索アプリケーションを更新することを忘れないでください。put search application commandを使用して。

最後に、このテンプレートを使用したパラメータなしの検索は、すべてのドキュメントを返すデフォルト検索にフォールバックします:

Python

  1. resp = client.search_application.search(
  2. name="my_search_application",
  3. )
  4. print(resp)

Js

  1. const response = await client.searchApplication.search({
  2. name: "my_search_application",
  3. });
  4. console.log(response);

コンソール

  1. POST _application/search_application/my_search_application/_search

ELSER検索

この例は、ELSER検索の簡略化されたバージョンをサポートします。

Python

  1. resp = client.search_application.put(
  2. name="my_search_application",
  3. search_application={
  4. "indices": [
  5. "index1",
  6. "index2"
  7. ],
  8. "template": {
  9. "script": {
  10. "lang": "mustache",
  11. "source": "\n {\n \"query\": {\n \"bool\": {\n \"should\": [\n {{#elser_fields}}\n {\n \"sparse_vector\": {\n \"field\": \"ml.inference.{{.}}_expanded.predicted_value\",\n \"inference_id\": \"<elser_inference_id>\",\n \"query\": \"{{query_string}}\"\n }\n },\n {{/elser_fields}}\n ]\n }\n },\n \"min_score\": \"{{min_score}}\"\n }\n ",
  12. "params": {
  13. "query_string": "*",
  14. "min_score": "10",
  15. "elser_fields": [
  16. {
  17. "name": "title"
  18. },
  19. {
  20. "name": "description"
  21. }
  22. ]
  23. }
  24. }
  25. }
  26. },
  27. )
  28. print(resp)

Js

  1. const response = await client.searchApplication.put({
  2. name: "my_search_application",
  3. search_application: {
  4. indices: ["index1", "index2"],
  5. template: {
  6. script: {
  7. lang: "mustache",
  8. source:
  9. '\n {\n "query": {\n "bool": {\n "should": [\n {{#elser_fields}}\n {\n "sparse_vector": {\n "field": "ml.inference.{{.}}_expanded.predicted_value",\n "inference_id": "<elser_inference_id>",\n "query": "{{query_string}}"\n }\n },\n {{/elser_fields}}\n ]\n }\n },\n "min_score": "{{min_score}}"\n }\n ',
  10. params: {
  11. query_string: "*",
  12. min_score: "10",
  13. elser_fields: [
  14. {
  15. name: "title",
  16. },
  17. {
  18. name: "description",
  19. },
  20. ],
  21. },
  22. },
  23. },
  24. },
  25. });
  26. console.log(response);

コンソール

  1. PUT _application/search_application/my_search_application
  2. {
  3. "indices": [
  4. "index1",
  5. "index2"
  6. ],
  7. "template": {
  8. "script": {
  9. "lang": "mustache",
  10. "source": """
  11. {
  12. "query": {
  13. "bool": {
  14. "should": [
  15. {{#elser_fields}}
  16. {
  17. "sparse_vector": {
  18. "field": "ml.inference.{{.}}_expanded.predicted_value",
  19. "inference_id": "<elser_inference_id>",
  20. "query": "{{query_string}}"
  21. }
  22. },
  23. {{/elser_fields}}
  24. ]
  25. }
  26. },
  27. "min_score": "{{min_score}}"
  28. }
  29. """,
  30. "params": {
  31. "query_string": "*",
  32. "min_score": "10",
  33. "elser_fields": [
  34. {
  35. "name": "title"
  36. },
  37. {
  38. "name": "description"
  39. }
  40. ]
  41. }
  42. }
  43. }
  44. }
  1. このテンプレートのサンプルクエリは次のようになります:
  2. #### Python
  3. ``````python
  4. resp = client.search_application.search(
  5. name="my_search_application",
  6. params={
  7. "query_string": "Where is the best place for mountain climbing?"
  8. },
  9. )
  10. print(resp)
  11. `

Js

  1. const response = await client.searchApplication.search({
  2. name: "my_search_application",
  3. params: {
  4. query_string: "Where is the best place for mountain climbing?",
  5. },
  6. });
  7. console.log(response);

コンソール

  1. POST _application/search_application/my_search_application/_search
  2. {
  3. "params": {
  4. "query_string": "Where is the best place for mountain climbing?"
  5. }
  6. }

kNN検索

この例はk近傍検索 (kNN)をサポートします。

正確なkNN検索をサポートするテンプレートは次のようになります:

Python

  1. resp = client.search_application.put(
  2. name="my_search_application",
  3. search_application={
  4. "indices": [
  5. "index1"
  6. ],
  7. "template": {
  8. "script": {
  9. "lang": "mustache",
  10. "source": "\n {\n \"query\": {\n \"script_score\": {\n \"query\": {\n \"bool\": {\n \"filter\": {\n \"range\": {\n \"{{field}}\": {\n \"{{operator}}\": {{value}}\n }\n }\n }\n }\n },\n \"script\": {\n \"source\": \"cosineSimilarity({{#toJson}}query_vector{{/toJson}}, '{{dense_vector_field}}') + 1.0\"\n }\n }\n }\n }\n ",
  11. "params": {
  12. "field": "price",
  13. "operator": "gte",
  14. "value": 1000,
  15. "dense_vector_field": "product-vector",
  16. "query_vector": []
  17. }
  18. }
  19. }
  20. },
  21. )
  22. print(resp)

Js

  1. const response = await client.searchApplication.put({
  2. name: "my_search_application",
  3. search_application: {
  4. indices: ["index1"],
  5. template: {
  6. script: {
  7. lang: "mustache",
  8. source:
  9. '\n {\n "query": {\n "script_score": {\n "query": {\n "bool": {\n "filter": {\n "range": {\n "{{field}}": {\n "{{operator}}": {{value}}\n }\n }\n }\n }\n },\n "script": {\n "source": "cosineSimilarity({{#toJson}}query_vector{{/toJson}}, \'{{dense_vector_field}}\') + 1.0"\n }\n }\n }\n }\n ',
  10. params: {
  11. field: "price",
  12. operator: "gte",
  13. value: 1000,
  14. dense_vector_field: "product-vector",
  15. query_vector: [],
  16. },
  17. },
  18. },
  19. },
  20. });
  21. console.log(response);

コンソール

  1. PUT _application/search_application/my_search_application
  2. {
  3. "indices": [
  4. "index1"
  5. ],
  6. "template": {
  7. "script": {
  8. "lang": "mustache",
  9. "source": """
  10. {
  11. "query": {
  12. "script_score": {
  13. "query": {
  14. "bool": {
  15. "filter": {
  16. "range": {
  17. "{{field}}": {
  18. "{{operator}}": {{value}}
  19. }
  20. }
  21. }
  22. }
  23. },
  24. "script": {
  25. "source": "cosineSimilarity({{#toJson}}query_vector{{/toJson}}, '{{dense_vector_field}}') + 1.0"
  26. }
  27. }
  28. }
  29. }
  30. """,
  31. "params": {
  32. "field": "price",
  33. "operator": "gte",
  34. "value": 1000,
  35. "dense_vector_field": "product-vector",
  36. "query_vector": []
  37. }
  38. }
  39. }
  40. }

このテンプレートを使用した検索クエリは次のようになります:

Python

  1. resp = client.search_application.search(
  2. name="my_search_application",
  3. params={
  4. "field": "price",
  5. "operator": "gte",
  6. "value": 500
  7. },
  8. )
  9. print(resp)

Js

  1. const response = await client.searchApplication.search({
  2. name: "my_search_application",
  3. params: {
  4. field: "price",
  5. operator: "gte",
  6. value: 500,
  7. },
  8. });
  9. console.log(response);

コンソール

  1. POST _application/search_application/my_search_application/_search
  2. {
  3. "params": {
  4. "field": "price",
  5. "operator": "gte",
  6. "value": 500
  7. }
  8. }

近似kNN検索をサポートするテンプレートは次のようになります:

Python

  1. resp = client.search_application.put(
  2. name="my_search_application",
  3. search_application={
  4. "indices": [
  5. "index1"
  6. ],
  7. "template": {
  8. "script": {
  9. "lang": "mustache",
  10. "source": "\n {\n \"knn\": {\n \"field\": \"{{knn_field}}\",\n \"query_vector\": {{#toJson}}query_vector{{/toJson}},\n \"k\": \"{{k}}\",\n \"num_candidates\": {{num_candidates}}\n },\n \"fields\": {{#toJson}}fields{{/toJson}}\n }\n ",
  11. "params": {
  12. "knn_field": "image-vector",
  13. "query_vector": [],
  14. "k": 10,
  15. "num_candidates": 100,
  16. "fields": [
  17. "title",
  18. "file-type"
  19. ]
  20. }
  21. }
  22. }
  23. },
  24. )
  25. print(resp)

Js

  1. const response = await client.searchApplication.put({
  2. name: "my_search_application",
  3. search_application: {
  4. indices: ["index1"],
  5. template: {
  6. script: {
  7. lang: "mustache",
  8. source:
  9. '\n {\n "knn": {\n "field": "{{knn_field}}",\n "query_vector": {{#toJson}}query_vector{{/toJson}},\n "k": "{{k}}",\n "num_candidates": {{num_candidates}}\n },\n "fields": {{#toJson}}fields{{/toJson}}\n }\n ',
  10. params: {
  11. knn_field: "image-vector",
  12. query_vector: [],
  13. k: 10,
  14. num_candidates: 100,
  15. fields: ["title", "file-type"],
  16. },
  17. },
  18. },
  19. },
  20. });
  21. console.log(response);

コンソール

  1. PUT _application/search_application/my_search_application
  2. {
  3. "indices": [
  4. "index1"
  5. ],
  6. "template": {
  7. "script": {
  8. "lang": "mustache",
  9. "source": """
  10. {
  11. "knn": {
  12. "field": "{{knn_field}}",
  13. "query_vector": {{#toJson}}query_vector{{/toJson}},
  14. "k": "{{k}}",
  15. "num_candidates": {{num_candidates}}
  16. },
  17. "fields": {{#toJson}}fields{{/toJson}}
  18. }
  19. """,
  20. "params": {
  21. "knn_field": "image-vector",
  22. "query_vector": [],
  23. "k": 10,
  24. "num_candidates": 100,
  25. "fields": ["title", "file-type"]
  26. }
  27. }
  28. }
  29. }

このテンプレートを使用した検索クエリは次のようになります:

Python

  1. resp = client.search_application.search(
  2. name="my_search_application",
  3. params={
  4. "knn_field": "image-vector",
  5. "query_vector": [
  6. -5,
  7. 9,
  8. -12
  9. ],
  10. "k": 10,
  11. "num_candidates": 100,
  12. "fields": [
  13. "title",
  14. "file-type"
  15. ]
  16. },
  17. )
  18. print(resp)

Js

  1. const response = await client.searchApplication.search({
  2. name: "my_search_application",
  3. params: {
  4. knn_field: "image-vector",
  5. query_vector: [-5, 9, -12],
  6. k: 10,
  7. num_candidates: 100,
  8. fields: ["title", "file-type"],
  9. },
  10. });
  11. console.log(response);

コンソール

  1. POST _application/search_application/my_search_application/_search
  2. {
  3. "params": {
  4. "knn_field": "image-vector",
  5. "query_vector": [-5, 9, -12],
  6. "k": 10,
  7. "num_candidates": 100,
  8. "fields": ["title", "file-type"]
  9. }
  10. }