クエリ時にフィールド値をオーバーライドする

マッピングに既に存在するフィールドと同じ名前のランタイムフィールドを作成すると、ランタイムフィールドはマッピングされたフィールドを隠します。クエリ時に、Elasticsearchはランタイムフィールドを評価し、スクリプトに基づいて値を計算し、その値をクエリの一部として返します。ランタイムフィールドがマッピングされたフィールドを隠すため、マッピングされたフィールドを変更することなく、検索で返される値をオーバーライドできます。

例えば、次のドキュメントを my-index-000001 にインデックスしたとしましょう:

Python

  1. resp = client.bulk(
  2. index="my-index-000001",
  3. refresh=True,
  4. operations=[
  5. {
  6. "index": {}
  7. },
  8. {
  9. "@timestamp": 1516729294000,
  10. "model_number": "QVKC92Q",
  11. "measures": {
  12. "voltage": 5.2
  13. }
  14. },
  15. {
  16. "index": {}
  17. },
  18. {
  19. "@timestamp": 1516642894000,
  20. "model_number": "QVKC92Q",
  21. "measures": {
  22. "voltage": 5.8
  23. }
  24. },
  25. {
  26. "index": {}
  27. },
  28. {
  29. "@timestamp": 1516556494000,
  30. "model_number": "QVKC92Q",
  31. "measures": {
  32. "voltage": 5.1
  33. }
  34. },
  35. {
  36. "index": {}
  37. },
  38. {
  39. "@timestamp": 1516470094000,
  40. "model_number": "QVKC92Q",
  41. "measures": {
  42. "voltage": 5.6
  43. }
  44. },
  45. {
  46. "index": {}
  47. },
  48. {
  49. "@timestamp": 1516383694000,
  50. "model_number": "HG537PU",
  51. "measures": {
  52. "voltage": 4.2
  53. }
  54. },
  55. {
  56. "index": {}
  57. },
  58. {
  59. "@timestamp": 1516297294000,
  60. "model_number": "HG537PU",
  61. "measures": {
  62. "voltage": 4
  63. }
  64. }
  65. ],
  66. )
  67. print(resp)

Ruby

  1. response = client.bulk(
  2. index: 'my-index-000001',
  3. refresh: true,
  4. body: [
  5. {
  6. index: {}
  7. },
  8. {
  9. "@timestamp": 1_516_729_294_000,
  10. model_number: 'QVKC92Q',
  11. measures: {
  12. voltage: 5.2
  13. }
  14. },
  15. {
  16. index: {}
  17. },
  18. {
  19. "@timestamp": 1_516_642_894_000,
  20. model_number: 'QVKC92Q',
  21. measures: {
  22. voltage: 5.8
  23. }
  24. },
  25. {
  26. index: {}
  27. },
  28. {
  29. "@timestamp": 1_516_556_494_000,
  30. model_number: 'QVKC92Q',
  31. measures: {
  32. voltage: 5.1
  33. }
  34. },
  35. {
  36. index: {}
  37. },
  38. {
  39. "@timestamp": 1_516_470_094_000,
  40. model_number: 'QVKC92Q',
  41. measures: {
  42. voltage: 5.6
  43. }
  44. },
  45. {
  46. index: {}
  47. },
  48. {
  49. "@timestamp": 1_516_383_694_000,
  50. model_number: 'HG537PU',
  51. measures: {
  52. voltage: 4.2
  53. }
  54. },
  55. {
  56. index: {}
  57. },
  58. {
  59. "@timestamp": 1_516_297_294_000,
  60. model_number: 'HG537PU',
  61. measures: {
  62. voltage: 4
  63. }
  64. }
  65. ]
  66. )
  67. puts response

Js

  1. const response = await client.bulk({
  2. index: "my-index-000001",
  3. refresh: "true",
  4. operations: [
  5. {
  6. index: {},
  7. },
  8. {
  9. "@timestamp": 1516729294000,
  10. model_number: "QVKC92Q",
  11. measures: {
  12. voltage: 5.2,
  13. },
  14. },
  15. {
  16. index: {},
  17. },
  18. {
  19. "@timestamp": 1516642894000,
  20. model_number: "QVKC92Q",
  21. measures: {
  22. voltage: 5.8,
  23. },
  24. },
  25. {
  26. index: {},
  27. },
  28. {
  29. "@timestamp": 1516556494000,
  30. model_number: "QVKC92Q",
  31. measures: {
  32. voltage: 5.1,
  33. },
  34. },
  35. {
  36. index: {},
  37. },
  38. {
  39. "@timestamp": 1516470094000,
  40. model_number: "QVKC92Q",
  41. measures: {
  42. voltage: 5.6,
  43. },
  44. },
  45. {
  46. index: {},
  47. },
  48. {
  49. "@timestamp": 1516383694000,
  50. model_number: "HG537PU",
  51. measures: {
  52. voltage: 4.2,
  53. },
  54. },
  55. {
  56. index: {},
  57. },
  58. {
  59. "@timestamp": 1516297294000,
  60. model_number: "HG537PU",
  61. measures: {
  62. voltage: 4,
  63. },
  64. },
  65. ],
  66. });
  67. console.log(response);

コンソール

  1. POST my-index-000001/_bulk?refresh=true
  2. {"index":{}}
  3. {"@timestamp":1516729294000,"model_number":"QVKC92Q","measures":{"voltage":5.2}}
  4. {"index":{}}
  5. {"@timestamp":1516642894000,"model_number":"QVKC92Q","measures":{"voltage":5.8}}
  6. {"index":{}}
  7. {"@timestamp":1516556494000,"model_number":"QVKC92Q","measures":{"voltage":5.1}}
  8. {"index":{}}
  9. {"@timestamp":1516470094000,"model_number":"QVKC92Q","measures":{"voltage":5.6}}
  10. {"index":{}}
  11. {"@timestamp":1516383694000,"model_number":"HG537PU","measures":{"voltage":4.2}}
  12. {"index":{}}
  13. {"@timestamp":1516297294000,"model_number":"HG537PU","measures":{"voltage":4.0}}

後で、HG537PU センサーが真の電圧を報告していないことに気付きます。インデックスされた値は、報告された値の 1.7 倍高いはずです!データを再インデックスする代わりに、_search リクエストの runtime_mappings セクションでスクリプトを定義して voltage フィールドを隠し、クエリ時に新しい値を計算できます。

モデル番号が HG537PU に一致するドキュメントを検索する場合:

Python

  1. resp = client.search(
  2. index="my-index-000001",
  3. query={
  4. "match": {
  5. "model_number": "HG537PU"
  6. }
  7. },
  8. )
  9. print(resp)

Ruby

  1. response = client.search(
  2. index: 'my-index-000001',
  3. body: {
  4. query: {
  5. match: {
  6. model_number: 'HG537PU'
  7. }
  8. }
  9. }
  10. )
  11. puts response

Js

  1. const response = await client.search({
  2. index: "my-index-000001",
  3. query: {
  4. match: {
  5. model_number: "HG537PU",
  6. },
  7. },
  8. });
  9. console.log(response);

コンソール

  1. GET my-index-000001/_search
  2. {
  3. "query": {
  4. "match": {
  5. "model_number": "HG537PU"
  6. }
  7. }
  8. }

レスポンスには、モデル番号 HG537PU に一致するドキュメントのインデックスされた値が含まれます:

コンソール-結果

  1. {
  2. ...
  3. "hits" : {
  4. "total" : {
  5. "value" : 2,
  6. "relation" : "eq"
  7. },
  8. "max_score" : 1.0296195,
  9. "hits" : [
  10. {
  11. "_index" : "my-index-000001",
  12. "_id" : "F1BeSXYBg_szTodcYCmk",
  13. "_score" : 1.0296195,
  14. "_source" : {
  15. "@timestamp" : 1516383694000,
  16. "model_number" : "HG537PU",
  17. "measures" : {
  18. "voltage" : 4.2
  19. }
  20. }
  21. },
  22. {
  23. "_index" : "my-index-000001",
  24. "_id" : "l02aSXYBkpNf6QRDO62Q",
  25. "_score" : 1.0296195,
  26. "_source" : {
  27. "@timestamp" : 1516297294000,
  28. "model_number" : "HG537PU",
  29. "measures" : {
  30. "voltage" : 4.0
  31. }
  32. }
  33. }
  34. ]
  35. }
  36. }

次のリクエストは、スクリプトが model_number フィールドを評価し、その値が HG537PU であるランタイムフィールドを定義します。一致するごとに、スクリプトは voltage フィールドの値を 1.7 で乗算します。

fields パラメータを _search API で使用すると、検索リクエストに一致するドキュメントの measures.voltage フィールドに対してスクリプトが計算した値を取得できます:

Python

  1. resp = client.search(
  2. index="my-index-000001",
  3. runtime_mappings={
  4. "measures.voltage": {
  5. "type": "double",
  6. "script": {
  7. "source": "if (doc['model_number.keyword'].value.equals('HG537PU'))\n {emit(1.7 * params._source['measures']['voltage']);}\n else{emit(params._source['measures']['voltage']);}"
  8. }
  9. }
  10. },
  11. query={
  12. "match": {
  13. "model_number": "HG537PU"
  14. }
  15. },
  16. fields=[
  17. "measures.voltage"
  18. ],
  19. )
  20. print(resp)

Ruby

  1. response = client.search(
  2. index: 'my-index-000001',
  3. body: {
  4. runtime_mappings: {
  5. 'measures.voltage' => {
  6. type: 'double',
  7. script: {
  8. source: "if (doc['model_number.keyword'].value.equals('HG537PU'))\n {emit(1.7 * params._source['measures']['voltage']);}\n else{emit(params._source['measures']['voltage']);}"
  9. }
  10. }
  11. },
  12. query: {
  13. match: {
  14. model_number: 'HG537PU'
  15. }
  16. },
  17. fields: [
  18. 'measures.voltage'
  19. ]
  20. }
  21. )
  22. puts response

Js

  1. const response = await client.search({
  2. index: "my-index-000001",
  3. runtime_mappings: {
  4. "measures.voltage": {
  5. type: "double",
  6. script: {
  7. source:
  8. "if (doc['model_number.keyword'].value.equals('HG537PU'))\n {emit(1.7 * params._source['measures']['voltage']);}\n else{emit(params._source['measures']['voltage']);}",
  9. },
  10. },
  11. },
  12. query: {
  13. match: {
  14. model_number: "HG537PU",
  15. },
  16. },
  17. fields: ["measures.voltage"],
  18. });
  19. console.log(response);

コンソール

  1. POST my-index-000001/_search
  2. {
  3. "runtime_mappings": {
  4. "measures.voltage": {
  5. "type": "double",
  6. "script": {
  7. "source":
  8. """if (doc['model_number.keyword'].value.equals('HG537PU'))
  9. {emit(1.7 * params._source['measures']['voltage']);}
  10. else{emit(params._source['measures']['voltage']);}"""
  11. }
  12. }
  13. },
  14. "query": {
  15. "match": {
  16. "model_number": "HG537PU"
  17. }
  18. },
  19. "fields": ["measures.voltage"]
  20. }

レスポンスを見てみると、各結果の measures.voltage に対する計算された値は 7.146.8 です。これが本来の姿です!ランタイムフィールドは、マッピングされた値を変更することなく、この値を検索リクエストの一部として計算しました。マッピングされた値は、レスポンスにまだ返されます:

コンソール-結果

  1. {
  2. ...
  3. "hits" : {
  4. "total" : {
  5. "value" : 2,
  6. "relation" : "eq"
  7. },
  8. "max_score" : 1.0296195,
  9. "hits" : [
  10. {
  11. "_index" : "my-index-000001",
  12. "_id" : "F1BeSXYBg_szTodcYCmk",
  13. "_score" : 1.0296195,
  14. "_source" : {
  15. "@timestamp" : 1516383694000,
  16. "model_number" : "HG537PU",
  17. "measures" : {
  18. "voltage" : 4.2
  19. }
  20. },
  21. "fields" : {
  22. "measures.voltage" : [
  23. 7.14
  24. ]
  25. }
  26. },
  27. {
  28. "_index" : "my-index-000001",
  29. "_id" : "l02aSXYBkpNf6QRDO62Q",
  30. "_score" : 1.0296195,
  31. "_source" : {
  32. "@timestamp" : 1516297294000,
  33. "model_number" : "HG537PU",
  34. "measures" : {
  35. "voltage" : 4.0
  36. }
  37. },
  38. "fields" : {
  39. "measures.voltage" : [
  40. 6.8
  41. ]
  42. }
  43. }
  44. ]
  45. }
  46. }