runtime field
的查询结果并不会在source
中出现,只是在查询时生成schema on read
。他的优势有如下几点:
- 在不需要重建索引的情况下向现有文档添加字段
- 在不了解数据结构的情况下开始处理数据
- 查询时覆盖从索引字段返回的值
- 在不修改
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>
发表评论 取消回复