runtime field 的查询结果并不会在 source 中出现,只是在查询时生成 schema on read 。他的优势有如下几点:

  1. 在不需要重建索引的情况下向现有文档添加字段
  2. 在不了解数据结构的情况下开始处理数据
  3. 查询时覆盖从索引字段返回的值
  4. 在不修改 Mapping 底层的情况下定义特殊用途的字段

注意:runtime field 字段的允许类型,可以从官网查看

# 创建运行时字段 host
PUT runtime-fields-test
{
  "mappings": {
    "runtime":{
      "host":{
        "type":"keyword",
        "script":{
          "source":"emit(doc['addr'].value + ':' + doc['port'].value)"
        }
      }
    },
    "properties":{
      "addr":{
        "type": "ip"
      },
      "port":{
        "type": "long"
      }
    }
  }
}
里边创建了运行时字段 host ,运行时字段(runtime fields) 不会创建索引,有 schema on read 特性,因此特性会在节省存储成本的同时提高摄取速度,并且可以在搜索请求、聚合、过滤和排序中使用它。
# 插入数据
POST runtime-fields-test/_bulk
{"index":{"_id":1}}
{"addr":"127.0.0.1", "port":"80"}
{"index":{"_id":2}}
{"addr":"127.0.0.2", "port":"443"}
{"index":{"_id":3}}
{"addr":"127.0.0.3", "port":"22"}
{"index":{"_id":4}}
{"addr":"127.0.0.4", "port":"3360"}
查询 host 字段
GET runtime-fields-test/_search?filter_path=*.hits
{
  "query": {
    "match": {
      "host":"127.0.0.1:80"
    }
  },
  "fields": [
    "host"
  ]
}
返回的数据结果
{
  "hits": {
    "hits": [
      {
        "_index": "runtime-fields-test",
        "_id": "1",
        "_score": 1,
        "_source": {
          "addr": "127.0.0.1",
          "port": "80"
        },
        "fields": {
          "host": [
            "127.0.0.1:80"
          ]
        }
      }
    ]
  }
}
我们如何删除 runtime fields
# 删除运行时字段
PUT runtime-fields-test/_mapping
{
  "runtime":{
    "host": null
  }
}

# 查看 mapping 已经删除了
GET runtime-fields-test/_mapping
然后就返回了我们想要的结果,上面是我们创建 mapping 的时候添加了 runtime fields 如果我们没有在创建时指定,如何查询?
# 这里我们创建一个新的字段,用户名、学分、成绩、创建时间
PUT runtime-fields-index
{
  "mappings": {
    "dynamic":"runtime",
    "properties": {
      "username":{
        "type": "text"
      },
      "credit":{
        "type": "integer"
      },
      "score":{
        "type": "double"
      },
      "create_time":{
        "type": "date",
        "format": ["yyyy-MM-dd HH:mm:ss"]
      }
    }
  }
}
插入数据
POST runtime-fields-index/_bulk
{"index":{"_id":1}}
{"username":"t1", "credit":"1", "score":"98", "create_time":"2023-01-01 23:00:00"}
{"index":{"_id":2}}
{"username":"t2", "credit":"2", "score":"90", "create_time":"2023-01-02 23:00:00"}
{"index":{"_id":3}}
{"username":"t3", "credit":"3", "score":"80", "create_time":"2023-01-03 23:00:00"}
{"index":{"_id":4}}
{"username":"t4", "credit":"4", "score":"85", "create_time":"2023-01-04 23:00:00"}
这个时候我们可以在查询的时候使用 runtime_mappings 来指定运行时字段,如下:
GET runtime-fields-index/_search?filter_path=**.hits
{
  "runtime_mappings": {
    "total_score": {    // 这里我们创建总积分,script 返回credit + score的值
      "type": "double",
      "script": {
        "source": "emit(doc['credit'].value + doc['score'].value)"
      }
    },
    "day_of_week": {
      "type": "keyword", // 显示创建时间星期几
      "script": {
        "source": "emit(doc['create_time'].value.dayOfWeekEnum.getDisplayName(TextStyle.FULL, Locale.ROOT))"
      }
    },
    "modify_score":{
      "type":"double",
      "script":{  // 判断total_score大于95分时候,总分数=总分数*1.1,否则返回原分数
        "source":"""
          if(doc['total_score'].size() > 0 && doc['total_score'].value > 95){
            emit(doc['total_score'].value * 1.1);
          }else{
            emit(doc['total_score'].value)
          }
        """
      }
    }
  },
  "query": {
    "bool": {
      "must_not": [    // 去除 username 是 t2 的数据
        {
          "match": {
            "username": "t2"
          }
        }
      ]
    }
  }, 
  "_source": false, // 不返回 _source信息
  "fields": [ // 返回所有字段信息
    "total_score",
    "day_of_week",
    "modify_score"
  ],
  "aggs": {
    "score avg": { // 返回runtime fields中 total_score平均分
      "avg": {
        "field": "total_score"
      }
    }
  }, 
  "sort": [ // 按照总分数来排序
    {
      "total_score": {
        "order": "desc"
      }
    }
  ]
}
我们在查询时候可以通过 runtime fields 来搜索、查询、聚合、排序出我们想要的数据,但是一定要注意优化,虽然 runtime fields 让搜索更灵活,但是也是会损失性能,所以一定要注意性能优化,尽量在设计时就设计好 mapping

<mark>... 未完待续</mark>

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论
立即
投稿

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部