当前位置 : 主页 > 编程语言 > java >

elasticsearch中使用runtime fields

来源:互联网 收集:自由互联 发布时间:2023-02-04
1、背景 在我们使用es的开发过程中可能会遇到这么一种情况,比如我们的线路名称字段lineName字段在设置mapping的时候使用的是text类型,但是后期发现需要使用这个字段来进行聚合操作

1、背景

在我们使用es的开发过程中可能会遇到这么一种情况,比如我们的线路名称字段lineName字段在设置mapping的时候使用的是text类型,但是后期发现需要使用这个字段来进行聚合操作,那么我们除了对索引进行reindex操作外,还有什么办法可以解决这个问题呢?此处我们通过runtime field来解决。

2、runtime field介绍

2.1 runtime field可以实现的功能

运行时字段是在查询时评估的字段。是在es7.11之后增加的运行时字段使您能够:

  • 将字段添加到现有文档,而无需重新索引数据
  • 在不了解数据结构的情况下开始处理数据
  • 在查询时覆盖从索引字段返回的值
  • 定义特定用途的字段,而不修改原始mapping runtime field 的作用
  • 2.2 runtime field优缺点

  • runtime field是运行时增加的字段,不会被索引和存储,不会增加索引的大小。
  • runtime field 可以像普通字段一样使用,可以进行查询,排序,聚合等操作。
  • 可以动态的添加字段。
  • 可以在查询时覆盖字段的值。即fields中和_source中可以返回同名的字段,但是值可能不一样。
  • 阻止mapping爆炸,可以先使用后定义。
  • 针对经常被搜索或聚合等操作的字段,不适合使用runtime field,而应该定义在mapping中。
  • runtime field不会出现在_source中,需要通过fields api来获取。
  • 3、创建runtime field的方式

    3.1 通过mapping的方式创建

    3.1.1、添加runtime field

    PUT /index_script_fields { "mappings": { "runtime": { "aggLineName": { "type": "keyword", "script": { "source": "emit(doc['lineName'].value)" } } }, "properties": { "lineId": { "type": "keyword" }, "lineName": { "type": "text" } } } }

    3.1.2、更新 runtime field

    POST /index_script_fields/_mapping { "runtime": { "aggLineName": { "type": "keyword", "script": { "source": "emit(doc['lineName'].value)" } } } }

    3.1.3、删除runtime field

    POST /index_script_fields/_mapping { "runtime": { "aggLineName": null } }

    3.2 通过search request定义runtime field

    GET /index_script_fields/_search { "runtime_mappings": { "lineName": { "type": "keyword", "script": "emit(params['_source']['lineName']+'new')" } }, "query": { "match_all": {} }, "fields": [ "lineName" ] }

    通过search request定义runtime field

    4、需求

    我们存在一个线路mapping,其中lineName在设计的使用使用了text类型,现在我们需要根据这个字段来进行聚合操作,那么使用runtime field该如何操作呢?

    5、实现

    5.1 mapping

    PUT /index_script_fields { "mappings": { "properties": { "lineId": { "type": "keyword" }, "lineName": { "type": "text" } } } }

    注意此时的lineName的类型是text

    5.2 插入数据

    PUT /index_script_fields/_bulk {"index":{"_id":1}} {"lineId":"line-01","lineName":"线路A"} {"index":{"_id":2}} {"lineId":"line-01","lineName":"线路A"} {"index":{"_id":3}} {"lineId":"line-02","lineName":"线路C"}

    5.3、根据线路来进行聚合

    从上方的mapping中可以lineName是text类型,是不可进行聚合操作的,那么此时我们想进行聚合操作,就可以使用runtime field来实现。

    5.3.1 不使用runtime field

    不使用runtime field

    5.3.2 使用runtime field

    5.3.2.1 dsl

    GET /index_script_fields/_search { "runtime_mappings": { "aggLineName": { "type": "keyword", "script": "emit(params['_source']['lineName']+'new')" } }, "query": { "match_all": {} }, "fields": [ "lineName" ], "aggs": { "agg_line_name": { "terms": { "field": "aggLineName", "size": 10 } } } }

    5.3.2.2 java代码

    @Test @DisplayName("lineName字段是text类型,无法进行聚合操作,定义一个runtime field来进行聚合操作") public void test01() throws IOException { SearchRequest request = SearchRequest.of(searchRequest -> searchRequest.index(INDEX_NAME) // 查询所有数据 .query(query -> query.matchAll(matchAll -> matchAll)) // runtime field字段不会出现在 _source中,需要使用使用 fields api来获取 .fields(fields -> fields.field("lineName")) // 创建一个 runtime filed 字段类型是 keyword .runtimeMappings("aggLineName", runtime -> runtime // 此处给字段类型为keyword .type(RuntimeFieldType.Keyword) .script(script -> script.inline(inline -> // runtime field中如果使用 painless脚本语言,需要使用emit inline.lang(ScriptLanguage.Painless) .source("emit(params['_source']['lineName']+'new')") ) ) ) // 进行聚合操作 .aggregations("agg_line_name", agg -> // 此处的 aggLineName即为上一步runtime field的字段 agg.terms(terms -> terms.field("aggLineName").size(10)) ) .size(100) ); System.out.println("request: " + request); SearchResponse<Object> response = client.search(request, Object.class); System.out.println("response: " + response);

    5.3.3.3 运行结果

    聚合

    6、完整代码

    https://gitee.com/huan1993/spring-cloud-parent/blob/master/es/es8-api/src/main/java/com/huan/es8/runtimefield/RuntimeFieldCorrectMappingError.java

    7、参考链接

    1、https://www.elastic.co/guide/en/elasticsearch/reference/8.6/runtime.html

    上一篇:美团动态线程池实践思路
    下一篇:没有了
    网友评论