【官方文档翻译】映射 - 查询时覆盖字段值 - Elasticsearch

101 阅读2分钟

在查询时覆盖字段值

如果你创建了一个和现有的映射里的字段同名的运行时字段,此运行时字段会影射到映射的字段。在查询时,ES估算运行时字段,基于脚本计算出一个值,将值作为查询的一部分返回。因为运行时字段是映射字段的影射,你可以覆盖搜索返回的值而不需要改变映射字段。
例如:假如你索引了下面的文档到 my-index-000001

POST my-index-000001/_bulk?refresh=true
{"index":{}}
{"@timestamp":1516729294000,"model_number":"QVKC92Q","measures":{"voltage":5.2}}
{"index":{}}
{"@timestamp":1516642894000,"model_number":"QVKC92Q","measures":{"voltage":5.8}}
{"index":{}}
{"@timestamp":1516556494000,"model_number":"QVKC92Q","measures":{"voltage":5.1}}
{"index":{}}
{"@timestamp":1516470094000,"model_number":"QVKC92Q","measures":{"voltage":5.6}}
{"index":{}}
{"@timestamp":1516383694000,"model_number":"HG537PU","measures":{"voltage":4.2}}
{"index":{}}
{"@timestamp":1516297294000,"model_number":"HG537PU","measures":{"voltage":4.0}}

你后来意识到 HG537PU 传感器没有报告它们真实的电压。索引值应该是报告值的1.7倍!你可以在 _search 请求的 runtime_mappings 部分定义一个脚本来影射 voltage 字段并在查询时计算一个新的值。

如果你搜索模型号匹配 HG537PU 的文档:

GET my-index-000001/_search
{
  "query": {
    "match": {
      "model_number": "HG537PU"
    }
  }
}

响应中包含了文档中匹配型号 HG537PU 的索引后的值:

{
  ...
  "hits" : {
    "total" : {
      "value" : 2,
      "relation" : "eq"
    },
    "max_score" : 1.0296195,
    "hits" : [
      {
        "_index" : "my-index-000001",
        "_id" : "F1BeSXYBg_szTodcYCmk",
        "_score" : 1.0296195,
        "_source" : {
          "@timestamp" : 1516383694000,
          "model_number" : "HG537PU",
          "measures" : {
            "voltage" : 4.2
          }
        }
      },
      {
        "_index" : "my-index-000001",
        "_id" : "l02aSXYBkpNf6QRDO62Q",
        "_score" : 1.0296195,
        "_source" : {
          "@timestamp" : 1516297294000,
          "model_number" : "HG537PU",
          "measures" : {
            "voltage" : 4.0
          }
        }
      }
    ]
  }
}

下面的请求定义了一个运行时字段,其中的脚本计算型号字段的值为 HG537PU 的值。 每一次匹配,脚本对 voltage 字段的值乘以 1.7。
使用 _search API上的 fields参数,为搜索请求匹配到的文档,你可以检索脚本为 measures.voltage 字段计算出的值:

POST my-index-000001/_search
{
  "runtime_mappings": {
    "measures.voltage": {
      "type": "double",
      "script": {
        "source":
        """if (doc['model_number.keyword'].value.equals('HG537PU'))
        {emit(1.7 * params._source['measures']['voltage']);}
        else{emit(params._source['measures']['voltage']);}"""
      }
    }
  },
  "query": {
    "match": {
      "model_number": "HG537PU"
    }
  },
  "fields": ["measures.voltage"]
}

看这个响应,在每一个结果上为 measures.voltage 计算出的值是 7.146.8。这才对嘛!运行时字段计算出的这个值作为搜索请求的一部分,而且不会改变映射的值,它们仍然在响应里返回:

{
  ...
  "hits" : {
    "total" : {
      "value" : 2,
      "relation" : "eq"
    },
    "max_score" : 1.0296195,
    "hits" : [
      {
        "_index" : "my-index-000001",
        "_id" : "F1BeSXYBg_szTodcYCmk",
        "_score" : 1.0296195,
        "_source" : {
          "@timestamp" : 1516383694000,
          "model_number" : "HG537PU",
          "measures" : {
            "voltage" : 4.2
          }
        },
        "fields" : {
          "measures.voltage" : [
            7.14
          ]
        }
      },
      {
        "_index" : "my-index-000001",
        "_id" : "l02aSXYBkpNf6QRDO62Q",
        "_score" : 1.0296195,
        "_source" : {
          "@timestamp" : 1516297294000,
          "model_number" : "HG537PU",
          "measures" : {
            "voltage" : 4.0
          }
        },
        "fields" : {
          "measures.voltage" : [
            6.8
          ]
        }
      }
    ]
  }
}