Percolator field type

percolator フィールドタイプは、JSON構造をネイティブクエリに解析し、そのクエリを保存します。これにより、percolate queryが提供されたドキュメントと一致させることができます。

JSONオブジェクトを含む任意のフィールドは、パーコレーター フィールドとして構成できます。パーコレーター フィールドタイプには設定がありません。percolator フィールドタイプを構成するだけで、Elasticsearch にフィールドをクエリとして扱うよう指示できます。

次のマッピングが percolator フィールドタイプを query フィールドに構成します:

Python

  1. resp = client.indices.create(
  2. index="my-index-000001",
  3. mappings={
  4. "properties": {
  5. "query": {
  6. "type": "percolator"
  7. },
  8. "field": {
  9. "type": "text"
  10. }
  11. }
  12. },
  13. )
  14. print(resp)

Ruby

  1. response = client.indices.create(
  2. index: 'my-index-000001',
  3. body: {
  4. mappings: {
  5. properties: {
  6. query: {
  7. type: 'percolator'
  8. },
  9. field: {
  10. type: 'text'
  11. }
  12. }
  13. }
  14. }
  15. )
  16. puts response

Js

  1. const response = await client.indices.create({
  2. index: "my-index-000001",
  3. mappings: {
  4. properties: {
  5. query: {
  6. type: "percolator",
  7. },
  8. field: {
  9. type: "text",
  10. },
  11. },
  12. },
  13. });
  14. console.log(response);

Console

  1. PUT my-index-000001
  2. {
  3. "mappings": {
  4. "properties": {
  5. "query": {
  6. "type": "percolator"
  7. },
  8. "field": {
  9. "type": "text"
  10. }
  11. }
  12. }
  13. }

次に、クエリをインデックスできます:

Python

  1. resp = client.index(
  2. index="my-index-000001",
  3. id="match_value",
  4. document={
  5. "query": {
  6. "match": {
  7. "field": "value"
  8. }
  9. }
  10. },
  11. )
  12. print(resp)

Ruby

  1. response = client.index(
  2. index: 'my-index-000001',
  3. id: 'match_value',
  4. body: {
  5. query: {
  6. match: {
  7. field: 'value'
  8. }
  9. }
  10. }
  11. )
  12. puts response

Js

  1. const response = await client.index({
  2. index: "my-index-000001",
  3. id: "match_value",
  4. document: {
  5. query: {
  6. match: {
  7. field: "value",
  8. },
  9. },
  10. },
  11. });
  12. console.log(response);

Console

  1. PUT my-index-000001/_doc/match_value
  2. {
  3. "query": {
  4. "match": {
  5. "field": "value"
  6. }
  7. }
  8. }

パーコレーター クエリで参照されるフィールドは、すでにパーコレーションに使用されるインデックスに関連付けられたマッピングに存在する必要があります。これらのフィールドが存在することを確認するには、create index または update mapping API を介してマッピングを追加または更新します。

Reindexing your percolator queries

パーコレーター クエリの再インデックス化は、新しいリリースでの percolator フィールドタイプの改善を利用するために時々必要です。

パーコレーター クエリの再インデックス化は、reindex api を使用して再インデックス化できます。次のインデックスを見てみましょう。これはパーコレーター フィールドタイプを持っています:

Python

  1. resp = client.indices.create(
  2. index="index",
  3. mappings={
  4. "properties": {
  5. "query": {
  6. "type": "percolator"
  7. },
  8. "body": {
  9. "type": "text"
  10. }
  11. }
  12. },
  13. )
  14. print(resp)
  15. resp1 = client.indices.update_aliases(
  16. actions=[
  17. {
  18. "add": {
  19. "index": "index",
  20. "alias": "queries"
  21. }
  22. }
  23. ],
  24. )
  25. print(resp1)
  26. resp2 = client.index(
  27. index="queries",
  28. id="1",
  29. refresh=True,
  30. document={
  31. "query": {
  32. "match": {
  33. "body": "quick brown fox"
  34. }
  35. }
  36. },
  37. )
  38. print(resp2)

Ruby

  1. response = client.indices.create(
  2. index: 'index',
  3. body: {
  4. mappings: {
  5. properties: {
  6. query: {
  7. type: 'percolator'
  8. },
  9. body: {
  10. type: 'text'
  11. }
  12. }
  13. }
  14. }
  15. )
  16. puts response
  17. response = client.indices.update_aliases(
  18. body: {
  19. actions: [
  20. {
  21. add: {
  22. index: 'index',
  23. alias: 'queries'
  24. }
  25. }
  26. ]
  27. }
  28. )
  29. puts response
  30. response = client.index(
  31. index: 'queries',
  32. id: 1,
  33. refresh: true,
  34. body: {
  35. query: {
  36. match: {
  37. body: 'quick brown fox'
  38. }
  39. }
  40. }
  41. )
  42. puts response

Js

  1. const response = await client.indices.create({
  2. index: "index",
  3. mappings: {
  4. properties: {
  5. query: {
  6. type: "percolator",
  7. },
  8. body: {
  9. type: "text",
  10. },
  11. },
  12. },
  13. });
  14. console.log(response);
  15. const response1 = await client.indices.updateAliases({
  16. actions: [
  17. {
  18. add: {
  19. index: "index",
  20. alias: "queries",
  21. },
  22. },
  23. ],
  24. });
  25. console.log(response1);
  26. const response2 = await client.index({
  27. index: "queries",
  28. id: 1,
  29. refresh: "true",
  30. document: {
  31. query: {
  32. match: {
  33. body: "quick brown fox",
  34. },
  35. },
  36. },
  37. });
  38. console.log(response2);

Console

  1. PUT index
  2. {
  3. "mappings": {
  4. "properties": {
  5. "query" : {
  6. "type" : "percolator"
  7. },
  8. "body" : {
  9. "type": "text"
  10. }
  11. }
  12. }
  13. }
  14. POST _aliases
  15. {
  16. "actions": [
  17. {
  18. "add": {
  19. "index": "index",
  20. "alias": "queries"
  21. }
  22. }
  23. ]
  24. }
  25. PUT queries/_doc/1?refresh
  26. {
  27. "query" : {
  28. "match" : {
  29. "body" : "quick brown fox"
  30. }
  31. }
  32. }
インデックスのエイリアスを定義することを常にお勧めします。これにより、再インデックスシステム/アプリケーションが、パーコレーター クエリが異なるインデックスにあることを知るために変更する必要がなくなります。

新しいメジャーバージョンにアップグレードする場合、Elasticsearch の新しいバージョンがクエリを読み取ることができるようにするには、現在の Elasticsearch バージョンの新しいインデックスにクエリを再インデックス化する必要があります:

Python

  1. resp = client.indices.create(
  2. index="new_index",
  3. mappings={
  4. "properties": {
  5. "query": {
  6. "type": "percolator"
  7. },
  8. "body": {
  9. "type": "text"
  10. }
  11. }
  12. },
  13. )
  14. print(resp)
  15. resp1 = client.reindex(
  16. refresh=True,
  17. source={
  18. "index": "index"
  19. },
  20. dest={
  21. "index": "new_index"
  22. },
  23. )
  24. print(resp1)
  25. resp2 = client.indices.update_aliases(
  26. actions=[
  27. {
  28. "remove": {
  29. "index": "index",
  30. "alias": "queries"
  31. }
  32. },
  33. {
  34. "add": {
  35. "index": "new_index",
  36. "alias": "queries"
  37. }
  38. }
  39. ],
  40. )
  41. print(resp2)

Ruby

  1. response = client.indices.create(
  2. index: 'new_index',
  3. body: {
  4. mappings: {
  5. properties: {
  6. query: {
  7. type: 'percolator'
  8. },
  9. body: {
  10. type: 'text'
  11. }
  12. }
  13. }
  14. }
  15. )
  16. puts response
  17. response = client.reindex(
  18. refresh: true,
  19. body: {
  20. source: {
  21. index: 'index'
  22. },
  23. dest: {
  24. index: 'new_index'
  25. }
  26. }
  27. )
  28. puts response
  29. response = client.indices.update_aliases(
  30. body: {
  31. actions: [
  32. {
  33. remove: {
  34. index: 'index',
  35. alias: 'queries'
  36. }
  37. },
  38. {
  39. add: {
  40. index: 'new_index',
  41. alias: 'queries'
  42. }
  43. }
  44. ]
  45. }
  46. )
  47. puts response

Js

  1. const response = await client.indices.create({
  2. index: "new_index",
  3. mappings: {
  4. properties: {
  5. query: {
  6. type: "percolator",
  7. },
  8. body: {
  9. type: "text",
  10. },
  11. },
  12. },
  13. });
  14. console.log(response);
  15. const response1 = await client.reindex({
  16. refresh: "true",
  17. source: {
  18. index: "index",
  19. },
  20. dest: {
  21. index: "new_index",
  22. },
  23. });
  24. console.log(response1);
  25. const response2 = await client.indices.updateAliases({
  26. actions: [
  27. {
  28. remove: {
  29. index: "index",
  30. alias: "queries",
  31. },
  32. },
  33. {
  34. add: {
  35. index: "new_index",
  36. alias: "queries",
  37. },
  38. },
  39. ],
  40. });
  41. console.log(response2);

Console

  1. PUT new_index
  2. {
  3. "mappings": {
  4. "properties": {
  5. "query" : {
  6. "type" : "percolator"
  7. },
  8. "body" : {
  9. "type": "text"
  10. }
  11. }
  12. }
  13. }
  14. POST /_reindex?refresh
  15. {
  16. "source": {
  17. "index": "index"
  18. },
  19. "dest": {
  20. "index": "new_index"
  21. }
  22. }
  23. POST _aliases
  24. {
  25. "actions": [
  26. {
  27. "remove": {
  28. "index" : "index",
  29. "alias": "queries"
  30. }
  31. },
  32. {
  33. "add": {
  34. "index": "new_index",
  35. "alias": "queries"
  36. }
  37. }
  38. ]
  39. }
エイリアスがある場合は、新しいインデックスを指すように忘れないでください。

queries エイリアスを介して percolate クエリを実行:

Python

  1. resp = client.search(
  2. index="queries",
  3. query={
  4. "percolate": {
  5. "field": "query",
  6. "document": {
  7. "body": "fox jumps over the lazy dog"
  8. }
  9. }
  10. },
  11. )
  12. print(resp)

Ruby

  1. response = client.search(
  2. index: 'queries',
  3. body: {
  4. query: {
  5. percolate: {
  6. field: 'query',
  7. document: {
  8. body: 'fox jumps over the lazy dog'
  9. }
  10. }
  11. }
  12. }
  13. )
  14. puts response

Js

  1. const response = await client.search({
  2. index: "queries",
  3. query: {
  4. percolate: {
  5. field: "query",
  6. document: {
  7. body: "fox jumps over the lazy dog",
  8. },
  9. },
  10. },
  11. });
  12. console.log(response);

Console

  1. GET /queries/_search
  2. {
  3. "query": {
  4. "percolate" : {
  5. "field" : "query",
  6. "document" : {
  7. "body" : "fox jumps over the lazy dog"
  8. }
  9. }
  10. }
  11. }

新しいインデックスからの一致を返します:

Console-Result

  1. {
  2. "took": 3,
  3. "timed_out": false,
  4. "_shards": {
  5. "total": 1,
  6. "successful": 1,
  7. "skipped" : 0,
  8. "failed": 0
  9. },
  10. "hits": {
  11. "total" : {
  12. "value": 1,
  13. "relation": "eq"
  14. },
  15. "max_score": 0.13076457,
  16. "hits": [
  17. {
  18. "_index": "new_index",
  19. "_id": "1",
  20. "_score": 0.13076457,
  21. "_source": {
  22. "query": {
  23. "match": {
  24. "body": "quick brown fox"
  25. }
  26. }
  27. },
  28. "fields" : {
  29. "_percolator_document_slot" : [0]
  30. }
  31. }
  32. ]
  33. }
  34. }
パーコレーター クエリのヒットは、現在新しいインデックスから提示されています。

Optimizing query time text analysis

パーコレーターがパーコレーター候補の一致を検証するとき、クエリ時間のテキスト分析を実行し、実際にパーコレーター クエリをパーコレーションされるドキュメントに対して実行します。これは、各候補一致と percolate クエリが実行されるたびに行われます。クエリ時間のテキスト分析がクエリ解析の比較的高価な部分である場合、テキスト分析はパーコレーション時に費やされる時間の支配的な要因になる可能性があります。このクエリ解析のオーバーヘッドは、パーコレーターが多くの候補パーコレーター クエリの一致を検証する場合に顕著になる可能性があります。

パーコレーション時に最も高価なテキスト分析部分を回避するために、パーコレーター クエリをインデックスする際に高価なテキスト分析を行うことを選択できます。これには、2 つの異なるアナライザーを使用する必要があります。最初のアナライザーは、実行する必要があるテキスト分析を実行します (高価な部分)。2 番目のアナライザー (通常はホワイトスペース) は、最初のアナライザーが生成したトークンを分割します。次に、パーコレーター クエリをインデックスする前に、分析 API を使用して、より高価なアナライザーでクエリ テキストを分析する必要があります。分析 API の結果、トークンは、パーコレーター クエリ内の元のクエリ テキストを置き換えるために使用される必要があります。クエリは、マッピングからアナライザーをオーバーライドし、2 番目のアナライザーのみを使用するように構成することが重要です。ほとんどのテキストベースのクエリは、analyzer オプション (match, query_string, simple_query_string) をサポートしています。このアプローチを使用すると、高価なテキスト分析が何度も実行されるのではなく、一度だけ実行されます。

このワークフローを簡略化した例で示しましょう。

次のパーコレーター クエリをインデックスしたいとしましょう:

Js

  1. {
  2. "query" : {
  3. "match" : {
  4. "body" : {
  5. "query" : "missing bicycles"
  6. }
  7. }
  8. }
  9. }

これらの設定とマッピングで:

Python

  1. resp = client.indices.create(
  2. index="test_index",
  3. settings={
  4. "analysis": {
  5. "analyzer": {
  6. "my_analyzer": {
  7. "tokenizer": "standard",
  8. "filter": [
  9. "lowercase",
  10. "porter_stem"
  11. ]
  12. }
  13. }
  14. }
  15. },
  16. mappings={
  17. "properties": {
  18. "query": {
  19. "type": "percolator"
  20. },
  21. "body": {
  22. "type": "text",
  23. "analyzer": "my_analyzer"
  24. }
  25. }
  26. },
  27. )
  28. print(resp)

Ruby

  1. response = client.indices.create(
  2. index: 'test_index',
  3. body: {
  4. settings: {
  5. analysis: {
  6. analyzer: {
  7. my_analyzer: {
  8. tokenizer: 'standard',
  9. filter: [
  10. 'lowercase',
  11. 'porter_stem'
  12. ]
  13. }
  14. }
  15. }
  16. },
  17. mappings: {
  18. properties: {
  19. query: {
  20. type: 'percolator'
  21. },
  22. body: {
  23. type: 'text',
  24. analyzer: 'my_analyzer'
  25. }
  26. }
  27. }
  28. }
  29. )
  30. puts response

Js

  1. const response = await client.indices.create({
  2. index: "test_index",
  3. settings: {
  4. analysis: {
  5. analyzer: {
  6. my_analyzer: {
  7. tokenizer: "standard",
  8. filter: ["lowercase", "porter_stem"],
  9. },
  10. },
  11. },
  12. },
  13. mappings: {
  14. properties: {
  15. query: {
  16. type: "percolator",
  17. },
  18. body: {
  19. type: "text",
  20. analyzer: "my_analyzer",
  21. },
  22. },
  23. },
  24. });
  25. console.log(response);

Console

  1. PUT /test_index
  2. {
  3. "settings": {
  4. "analysis": {
  5. "analyzer": {
  6. "my_analyzer" : {
  7. "tokenizer": "standard",
  8. "filter" : ["lowercase", "porter_stem"]
  9. }
  10. }
  11. }
  12. },
  13. "mappings": {
  14. "properties": {
  15. "query" : {
  16. "type": "percolator"
  17. },
  18. "body" : {
  19. "type": "text",
  20. "analyzer": "my_analyzer"
  21. }
  22. }
  23. }
  24. }
この例の目的のために、このアナライザーは高価であると見なされます。

最初に、インデックスする前にテキスト分析を実行するために分析 API を使用する必要があります:

Python

  1. resp = client.indices.analyze(
  2. index="test_index",
  3. analyzer="my_analyzer",
  4. text="missing bicycles",
  5. )
  6. print(resp)

Ruby

  1. response = client.indices.analyze(
  2. index: 'test_index',
  3. body: {
  4. analyzer: 'my_analyzer',
  5. text: 'missing bicycles'
  6. }
  7. )
  8. puts response

Js

  1. const response = await client.indices.analyze({
  2. index: "test_index",
  3. analyzer: "my_analyzer",
  4. text: "missing bicycles",
  5. });
  6. console.log(response);

Console

  1. POST /test_index/_analyze
  2. {
  3. "analyzer" : "my_analyzer",
  4. "text" : "missing bicycles"
  5. }

これにより、次のレスポンスが得られます:

Console-Result

  1. {
  2. "tokens": [
  3. {
  4. "token": "miss",
  5. "start_offset": 0,
  6. "end_offset": 7,
  7. "type": "<ALPHANUM>",
  8. "position": 0
  9. },
  10. {
  11. "token": "bicycl",
  12. "start_offset": 8,
  13. "end_offset": 16,
  14. "type": "<ALPHANUM>",
  15. "position": 1
  16. }
  17. ]
  18. }

返された順序のすべてのトークンは、パーコレーター クエリ内のクエリ テキストを置き換える必要があります:

Python

  1. resp = client.index(
  2. index="test_index",
  3. id="1",
  4. refresh=True,
  5. document={
  6. "query": {
  7. "match": {
  8. "body": {
  9. "query": "miss bicycl",
  10. "analyzer": "whitespace"
  11. }
  12. }
  13. }
  14. },
  15. )
  16. print(resp)

Ruby

  1. response = client.index(
  2. index: 'test_index',
  3. id: 1,
  4. refresh: true,
  5. body: {
  6. query: {
  7. match: {
  8. body: {
  9. query: 'miss bicycl',
  10. analyzer: 'whitespace'
  11. }
  12. }
  13. }
  14. }
  15. )
  16. puts response

Js

  1. const response = await client.index({
  2. index: "test_index",
  3. id: 1,
  4. refresh: "true",
  5. document: {
  6. query: {
  7. match: {
  8. body: {
  9. query: "miss bicycl",
  10. analyzer: "whitespace",
  11. },
  12. },
  13. },
  14. },
  15. });
  16. console.log(response);

Console

  1. PUT /test_index/_doc/1?refresh
  2. {
  3. "query" : {
  4. "match" : {
  5. "body" : {
  6. "query" : "miss bicycl",
  7. "analyzer" : "whitespace"
  8. }
  9. }
  10. }
  11. }
ここでホワイトスペース アナライザーを選択することが重要です。そうしないと、マッピングで定義されたアナライザーが使用され、
このワークフローを使用する目的が無くなります。whitespace は組み込みアナライザーであり、異なるアナライザーを使用する必要がある場合は、最初にインデックスの設定で構成する必要があります。

パーコレーター フローのインデックス前に分析 API を実行する必要があります。

パーコレーション時には何も変更されず、percolate クエリは通常通り定義できます:

Python

  1. resp = client.search(
  2. index="test_index",
  3. query={
  4. "percolate": {
  5. "field": "query",
  6. "document": {
  7. "body": "Bycicles are missing"
  8. }
  9. }
  10. },
  11. )
  12. print(resp)

Ruby

  1. response = client.search(
  2. index: 'test_index',
  3. body: {
  4. query: {
  5. percolate: {
  6. field: 'query',
  7. document: {
  8. body: 'Bycicles are missing'
  9. }
  10. }
  11. }
  12. }
  13. )
  14. puts response

Js

  1. const response = await client.search({
  2. index: "test_index",
  3. query: {
  4. percolate: {
  5. field: "query",
  6. document: {
  7. body: "Bycicles are missing",
  8. },
  9. },
  10. },
  11. });
  12. console.log(response);

Console

  1. GET /test_index/_search
  2. {
  3. "query": {
  4. "percolate" : {
  5. "field" : "query",
  6. "document" : {
  7. "body" : "Bycicles are missing"
  8. }
  9. }
  10. }
  11. }

これにより、次のようなレスポンスが得られます:

Console-Result

  1. {
  2. "took": 6,
  3. "timed_out": false,
  4. "_shards": {
  5. "total": 1,
  6. "successful": 1,
  7. "skipped" : 0,
  8. "failed": 0
  9. },
  10. "hits": {
  11. "total" : {
  12. "value": 1,
  13. "relation": "eq"
  14. },
  15. "max_score": 0.13076457,
  16. "hits": [
  17. {
  18. "_index": "test_index",
  19. "_id": "1",
  20. "_score": 0.13076457,
  21. "_source": {
  22. "query": {
  23. "match": {
  24. "body": {
  25. "query": "miss bicycl",
  26. "analyzer": "whitespace"
  27. }
  28. }
  29. }
  30. },
  31. "fields" : {
  32. "_percolator_document_slot" : [0]
  33. }
  34. }
  35. ]
  36. }
  37. }

Optimizing wildcard queries.

ワイルドカードクエリは、特にワイルドカード式が大きい場合、パーコレーターにとって他のクエリよりも高価です。

wildcard クエリがプレフィックス ワイルドカード式を使用している場合や、単に prefix クエリを使用している場合、edge_ngram トークンフィルターを使用して、これらのクエリを term フィールドで edge_ngram トークンフィルターが構成されているフィールドの通常のクエリに置き換えることができます。

カスタム分析設定でインデックスを作成:

Python

  1. resp = client.indices.create(
  2. index="my_queries1",
  3. settings={
  4. "analysis": {
  5. "analyzer": {
  6. "wildcard_prefix": {
  7. "type": "custom",
  8. "tokenizer": "standard",
  9. "filter": [
  10. "lowercase",
  11. "wildcard_edge_ngram"
  12. ]
  13. }
  14. },
  15. "filter": {
  16. "wildcard_edge_ngram": {
  17. "type": "edge_ngram",
  18. "min_gram": 1,
  19. "max_gram": 32
  20. }
  21. }
  22. }
  23. },
  24. mappings={
  25. "properties": {
  26. "query": {
  27. "type": "percolator"
  28. },
  29. "my_field": {
  30. "type": "text",
  31. "fields": {
  32. "prefix": {
  33. "type": "text",
  34. "analyzer": "wildcard_prefix",
  35. "search_analyzer": "standard"
  36. }
  37. }
  38. }
  39. }
  40. },
  41. )
  42. print(resp)

Ruby

  1. response = client.indices.create(
  2. index: 'my_queries1',
  3. body: {
  4. settings: {
  5. analysis: {
  6. analyzer: {
  7. wildcard_prefix: {
  8. type: 'custom',
  9. tokenizer: 'standard',
  10. filter: [
  11. 'lowercase',
  12. 'wildcard_edge_ngram'
  13. ]
  14. }
  15. },
  16. filter: {
  17. wildcard_edge_ngram: {
  18. type: 'edge_ngram',
  19. min_gram: 1,
  20. max_gram: 32
  21. }
  22. }
  23. }
  24. },
  25. mappings: {
  26. properties: {
  27. query: {
  28. type: 'percolator'
  29. },
  30. my_field: {
  31. type: 'text',
  32. fields: {
  33. prefix: {
  34. type: 'text',
  35. analyzer: 'wildcard_prefix',
  36. search_analyzer: 'standard'
  37. }
  38. }
  39. }
  40. }
  41. }
  42. }
  43. )
  44. puts response

Js

  1. const response = await client.indices.create({
  2. index: "my_queries1",
  3. settings: {
  4. analysis: {
  5. analyzer: {
  6. wildcard_prefix: {
  7. type: "custom",
  8. tokenizer: "standard",
  9. filter: ["lowercase", "wildcard_edge_ngram"],
  10. },
  11. },
  12. filter: {
  13. wildcard_edge_ngram: {
  14. type: "edge_ngram",
  15. min_gram: 1,
  16. max_gram: 32,
  17. },
  18. },
  19. },
  20. },
  21. mappings: {
  22. properties: {
  23. query: {
  24. type: "percolator",
  25. },
  26. my_field: {
  27. type: "text",
  28. fields: {
  29. prefix: {
  30. type: "text",
  31. analyzer: "wildcard_prefix",
  32. search_analyzer: "standard",
  33. },
  34. },
  35. },
  36. },
  37. },
  38. });
  39. console.log(response);

Console

  1. PUT my_queries1
  2. {
  3. "settings": {
  4. "analysis": {
  5. "analyzer": {
  6. "wildcard_prefix": {
  7. "type": "custom",
  8. "tokenizer": "standard",
  9. "filter": [
  10. "lowercase",
  11. "wildcard_edge_ngram"
  12. ]
  13. }
  14. },
  15. "filter": {
  16. "wildcard_edge_ngram": {
  17. "type": "edge_ngram",
  18. "min_gram": 1,
  19. "max_gram": 32
  20. }
  21. }
  22. }
  23. },
  24. "mappings": {
  25. "properties": {
  26. "query": {
  27. "type": "percolator"
  28. },
  29. "my_field": {
  30. "type": "text",
  31. "fields": {
  32. "prefix": {
  33. "type": "text",
  34. "analyzer": "wildcard_prefix",
  35. "search_analyzer": "standard"
  36. }
  37. }
  38. }
  39. }
  40. }
  41. }
プレフィックス トークンをインデックス時にのみ生成するアナライザーです。
プレフィックス検索のニーズに基づいて min_gram を増加させ、max_gram 設定を減少させます。
このマルチフィールドは、term または match クエリを使用してプレフィックス検索を行うために使用する必要があります。

次に、次のクエリをインデックスする代わりに:

Js

  1. {
  2. "query": {
  3. "wildcard": {
  4. "my_field": "abc*"
  5. }
  6. }
  7. }

次のクエリをインデックスする必要があります:

Python

  1. resp = client.index(
  2. index="my_queries1",
  3. id="1",
  4. refresh=True,
  5. document={
  6. "query": {
  7. "term": {
  8. "my_field.prefix": "abc"
  9. }
  10. }
  11. },
  12. )
  13. print(resp)

Ruby

  1. response = client.index(
  2. index: 'my_queries1',
  3. id: 1,
  4. refresh: true,
  5. body: {
  6. query: {
  7. term: {
  8. 'my_field.prefix' => 'abc'
  9. }
  10. }
  11. }
  12. )
  13. puts response

Js

  1. const response = await client.index({
  2. index: "my_queries1",
  3. id: 1,
  4. refresh: "true",
  5. document: {
  6. query: {
  7. term: {
  8. "my_field.prefix": "abc",
  9. },
  10. },
  11. },
  12. });
  13. console.log(response);

Console

  1. PUT /my_queries1/_doc/1?refresh
  2. {
  3. "query": {
  4. "term": {
  5. "my_field.prefix": "abc"
  6. }
  7. }
  8. }

この方法は、最初のクエリよりも2 番目のクエリをより効率的に処理できます。

次の検索リクエストは、以前にインデックスされたパーコレーター クエリと一致します:

Python

  1. resp = client.search(
  2. index="my_queries1",
  3. query={
  4. "percolate": {
  5. "field": "query",
  6. "document": {
  7. "my_field": "abcd"
  8. }
  9. }
  10. },
  11. )
  12. print(resp)

Ruby

  1. response = client.search(
  2. index: 'my_queries1',
  3. body: {
  4. query: {
  5. percolate: {
  6. field: 'query',
  7. document: {
  8. my_field: 'abcd'
  9. }
  10. }
  11. }
  12. }
  13. )
  14. puts response

Js

  1. const response = await client.search({
  2. index: "my_queries1",
  3. query: {
  4. percolate: {
  5. field: "query",
  6. document: {
  7. my_field: "abcd",
  8. },
  9. },
  10. },
  11. });
  12. console.log(response);

Console

  1. GET /my_queries1/_search
  2. {
  3. "query": {
  4. "percolate": {
  5. "field": "query",
  6. "document": {
  7. "my_field": "abcd"
  8. }
  9. }
  10. }
  11. }

Console-Result

  1. {
  2. "took": 6,
  3. "timed_out": false,
  4. "_shards": {
  5. "total": 1,
  6. "successful": 1,
  7. "skipped": 0,
  8. "failed": 0
  9. },
  10. "hits": {
  11. "total" : {
  12. "value": 1,
  13. "relation": "eq"
  14. },
  15. "max_score": 0.18864399,
  16. "hits": [
  17. {
  18. "_index": "my_queries1",
  19. "_id": "1",
  20. "_score": 0.18864399,
  21. "_source": {
  22. "query": {
  23. "term": {
  24. "my_field.prefix": "abc"
  25. }
  26. }
  27. },
  28. "fields": {
  29. "_percolator_document_slot": [
  30. 0
  31. ]
  32. }
  33. }
  34. ]
  35. }
  36. }

同じ技術を使用して、サフィックス ワイルドカード検索を高速化することもできます。reverse トークンフィルターを edge_ngram トークンフィルターの前に使用します。

Python

  1. resp = client.indices.create(
  2. index="my_queries2",
  3. settings={
  4. "analysis": {
  5. "analyzer": {
  6. "wildcard_suffix": {
  7. "type": "custom",
  8. "tokenizer": "standard",
  9. "filter": [
  10. "lowercase",
  11. "reverse",
  12. "wildcard_edge_ngram"
  13. ]
  14. },
  15. "wildcard_suffix_search_time": {
  16. "type": "custom",
  17. "tokenizer": "standard",
  18. "filter": [
  19. "lowercase",
  20. "reverse"
  21. ]
  22. }
  23. },
  24. "filter": {
  25. "wildcard_edge_ngram": {
  26. "type": "edge_ngram",
  27. "min_gram": 1,
  28. "max_gram": 32
  29. }
  30. }
  31. }
  32. },
  33. mappings={
  34. "properties": {
  35. "query": {
  36. "type": "percolator"
  37. },
  38. "my_field": {
  39. "type": "text",
  40. "fields": {
  41. "suffix": {
  42. "type": "text",
  43. "analyzer": "wildcard_suffix",
  44. "search_analyzer": "wildcard_suffix_search_time"
  45. }
  46. }
  47. }
  48. }
  49. },
  50. )
  51. print(resp)

Ruby

  1. response = client.indices.create(
  2. index: 'my_queries2',
  3. body: {
  4. settings: {
  5. analysis: {
  6. analyzer: {
  7. wildcard_suffix: {
  8. type: 'custom',
  9. tokenizer: 'standard',
  10. filter: [
  11. 'lowercase',
  12. 'reverse',
  13. 'wildcard_edge_ngram'
  14. ]
  15. },
  16. wildcard_suffix_search_time: {
  17. type: 'custom',
  18. tokenizer: 'standard',
  19. filter: [
  20. 'lowercase',
  21. 'reverse'
  22. ]
  23. }
  24. },
  25. filter: {
  26. wildcard_edge_ngram: {
  27. type: 'edge_ngram',
  28. min_gram: 1,
  29. max_gram: 32
  30. }
  31. }
  32. }
  33. },
  34. mappings: {
  35. properties: {
  36. query: {
  37. type: 'percolator'
  38. },
  39. my_field: {
  40. type: 'text',
  41. fields: {
  42. suffix: {
  43. type: 'text',
  44. analyzer: 'wildcard_suffix',
  45. search_analyzer: 'wildcard_suffix_search_time'
  46. }
  47. }
  48. }
  49. }
  50. }
  51. }
  52. )
  53. puts response

Js

  1. const response = await client.indices.create({
  2. index: "my_queries2",
  3. settings: {
  4. analysis: {
  5. analyzer: {
  6. wildcard_suffix: {
  7. type: "custom",
  8. tokenizer: "standard",
  9. filter: ["lowercase", "reverse", "wildcard_edge_ngram"],
  10. },
  11. wildcard_suffix_search_time: {
  12. type: "custom",
  13. tokenizer: "standard",
  14. filter: ["lowercase", "reverse"],
  15. },
  16. },
  17. filter: {
  18. wildcard_edge_ngram: {
  19. type: "edge_ngram",
  20. min_gram: 1,
  21. max_gram: 32,
  22. },
  23. },
  24. },
  25. },
  26. mappings: {
  27. properties: {
  28. query: {
  29. type: "percolator",
  30. },
  31. my_field: {
  32. type: "text",
  33. fields: {
  34. suffix: {
  35. type: "text",
  36. analyzer: "wildcard_suffix",
  37. search_analyzer: "wildcard_suffix_search_time",
  38. },
  39. },
  40. },
  41. },
  42. },
  43. });
  44. console.log(response);

Console

  1. PUT my_queries2
  2. {
  3. "settings": {
  4. "analysis": {
  5. "analyzer": {
  6. "wildcard_suffix": {
  7. "type": "custom",
  8. "tokenizer": "standard",
  9. "filter": [
  10. "lowercase",
  11. "reverse",
  12. "wildcard_edge_ngram"
  13. ]
  14. },
  15. "wildcard_suffix_search_time": {
  16. "type": "custom",
  17. "tokenizer": "standard",
  18. "filter": [
  19. "lowercase",
  20. "reverse"
  21. ]
  22. }
  23. },
  24. "filter": {
  25. "wildcard_edge_ngram": {
  26. "type": "edge_ngram",
  27. "min_gram": 1,
  28. "max_gram": 32
  29. }
  30. }
  31. }
  32. },
  33. "mappings": {
  34. "properties": {
  35. "query": {
  36. "type": "percolator"
  37. },
  38. "my_field": {
  39. "type": "text",
  40. "fields": {
  41. "suffix": {
  42. "type": "text",
  43. "analyzer": "wildcard_suffix",
  44. "search_analyzer": "wildcard_suffix_search_time"
  45. }
  46. }
  47. }
  48. }
  49. }
  50. }
検索時にもカスタムアナライザーが必要です。そうしないと、クエリ用語が逆転せず、予約されたサフィックス トークンと一致しなくなります。

次に、次のクエリをインデックスする代わりに:

Js

  1. {
  2. "query": {
  3. "wildcard": {
  4. "my_field": "*xyz"
  5. }
  6. }
  7. }

次のクエリをインデックスする必要があります:

Python

  1. resp = client.index(
  2. index="my_queries2",
  3. id="2",
  4. refresh=True,
  5. document={
  6. "query": {
  7. "match": {
  8. "my_field.suffix": "xyz"
  9. }
  10. }
  11. },
  12. )
  13. print(resp)

Ruby

  1. response = client.index(
  2. index: 'my_queries2',
  3. id: 2,
  4. refresh: true,
  5. body: {
  6. query: {
  7. match: {
  8. 'my_field.suffix' => 'xyz'
  9. }
  10. }
  11. }
  12. )
  13. puts response

Js

  1. const response = await client.index({
  2. index: "my_queries2",
  3. id: 2,
  4. refresh: "true",
  5. document: {
  6. query: {
  7. match: {
  8. "my_field.suffix": "xyz",
  9. },
  10. },
  11. },
  12. });
  13. console.log(response);

Console

  1. PUT /my_queries2/_doc/2?refresh
  2. {
  3. "query": {
  4. "match": {
  5. "my_field.suffix": "xyz"
  6. }
  7. }
  8. }
match クエリは term クエリの代わりに使用する必要があります。テキスト分析はクエリ用語を逆転させる必要があります。

次の検索リクエストは、以前にインデックスされたパーコレーター クエリと一致します:

Python

  1. resp = client.search(
  2. index="my_queries2",
  3. query={
  4. "percolate": {
  5. "field": "query",
  6. "document": {
  7. "my_field": "wxyz"
  8. }
  9. }
  10. },
  11. )
  12. print(resp)

Ruby

  1. response = client.search(
  2. index: 'my_queries2',
  3. body: {
  4. query: {
  5. percolate: {
  6. field: 'query',
  7. document: {
  8. my_field: 'wxyz'
  9. }
  10. }
  11. }
  12. }
  13. )
  14. puts response

Js

  1. const response = await client.search({
  2. index: "my_queries2",
  3. query: {
  4. percolate: {
  5. field: "query",
  6. document: {
  7. my_field: "wxyz",
  8. },
  9. },
  10. },
  11. });
  12. console.log(response);

Console

  1. GET /my_queries2/_search
  2. {
  3. "query": {
  4. "percolate": {
  5. "field": "query",
  6. "document": {
  7. "my_field": "wxyz"
  8. }
  9. }
  10. }
  11. }

Dedicated Percolator Index

パーコレーター クエリは、任意のインデックスに追加できます。データが存在するインデックスにパーコレーター クエリを追加する代わりに、専用のインデックスにこれらのクエリを追加することもできます。この利点は、この専用のパーコレーター インデックスが独自のインデックス設定を持つことができることです (たとえば、プライマリ シャードとレプリカ シャードの数)。専用のパーコレーター インデックスを持つことを選択した場合、通常のインデックスのマッピングもパーコレーター インデックスで利用できることを確認する必要があります。そうしないと、パーコレーター クエリが正しく解析されない可能性があります。

Forcing Unmapped Fields to be Handled as Strings

特定のケースでは、どのようなパーコレーター クエリが登録されるかが不明であり、パーコレーター クエリによって参照されるフィールドにマッピングが存在しない場合、パーコレーター クエリの追加が失敗します。これは、マッピングを更新して適切な設定を持つフィールドを持つ必要があることを意味し、その後、パーコレーター クエリを追加できます。しかし、すべての未マッピング フィールドがデフォルトのテキスト フィールドとして処理される場合は、十分な場合もあります。その場合、index.percolator.map_unmapped_fields_as_text 設定を true (デフォルトは false) に構成し、パーコレーター クエリで参照されるフィールドが存在しない場合は、デフォルトのテキスト フィールドとして処理されるため、パーコレーター クエリの追加が失敗しません。

Limitations

Parent/child

percolate クエリは、1 回のドキュメントを処理しているため、has_childhas_parent のような子ドキュメントに対して実行されるクエリやフィルターをサポートしていません。

Fetching queries

クエリ解析中に get コールを介してデータを取得するクエリがいくつかあります。たとえば、terms クエリは、用語ルックアップを使用している場合、template クエリはインデックスされたスクリプトを使用している場合、geo_shape は事前インデックスされたシェイプを使用している場合です。これらのクエリが percolator フィールドタイプによってインデックスされると、get コールは 1 回実行されます。したがって、percolator クエリがこれらのクエリを評価するたびに、インデックス時にあった用語、シェイプなどが使用されます。重要な点は、これらのクエリが行う用語の取得は、パーコレーター クエリがプライマリ シャードとレプリカ シャードの両方でインデックスされるたびに発生するため、インデックスされた用語はシャードコピー間で異なる可能性があることです。インデックス中にソースインデックスが変更された場合。

Script query

script クエリ内のスクリプトは、doc 値フィールドにのみアクセスできます。percolate クエリは、提供されたドキュメントをメモリ内インデックスにインデックスします。このメモリ内インデックスは、保存されたフィールドをサポートしておらず、そのため _source フィールドや他の保存されたフィールドは保存されません。これは、script クエリで _source および他の保存されたフィールドが利用できない理由です。

Field aliases

フィールドエイリアスを含むパーコレーター クエリは、常に期待どおりに動作するとは限りません。特に、フィールドエイリアスを含むパーコレーター クエリが登録され、その後そのエイリアスが異なるフィールドを参照するようにマッピングで更新された場合、保存されたクエリは元のターゲットフィールドを参照し続けます。フィールドエイリアスの変更を反映させるには、パーコレーター クエリを明示的に再インデックス化する必要があります。