当前位置: 首页 > 科技观察

Elasticsearch使用RuntimeFields

时间:2023-03-12 22:57:38 科技观察

1。背景在使用es的开发过程中,我们可能会遇到这样的情况。比如我们的行名字段lineName字段在设置映射的时候使用的是text类型,但是后来发现这个字段需要用于聚合操作,那么除了重新索引索引之外,我们还能做些什么来解决这个问题呢?这里我们使用runtime字段来解决。2.运行时字段介绍2.1运行时字段可以实现的功能运行时字段是在查询时求值的字段。在ES7.11之后添加的运行时字段使您能够:在不重新索引数据的情况下向现有文档添加字段在不了解数据结构的情况下开始处理数据在查询时覆盖从索引字段定义返回的值在不修改原始映射的情况下实现特定目的。运行时字段的作用2.2运行时字段的优缺点运行时字段是在运行时添加的字段,不会被索引和存储,不会增加索引的大小。运行时字段可以像普通字段一样使用,可以进行查询、排序、聚合等操作。可以动态添加字段。字段值可以在查询时被覆盖。即fields和_source中可以返回同名的字段,但值可能不同。为防止映射爆炸,可以先使用再定义。对于经常搜索或者聚合的字段,不适合使用runtime字段,应该在mapping中定义。runtime字段不会出现在_source中,需要通过fieldsapi获取。3.运行时域的创建方法3.1通过映射创建3.1.1.添加运行时字段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、更新运行时字段POST/index_script_fields/_mapping{"runtime":{"aggLineName":{"type":"keyword","script":{"source":"emit(doc['lineName'].value)"}}}}3.1.3。删除runtimefieldPOST/index_script_fields/_mapping{"runtime":{"aggLineName":null}}3.2定义runtimefieldGET/index_script_fields/_search{"通过搜索请求runtime_mappings":{"lineName":{"type":"keyword",“脚本”:“发出(参数['_source']['lineName']+'new')”}},“查询”:{“match_all”:{}},“字段”:[“lineName”]}定义按搜索请求运行时间场4。需求我们有一个线映射,其中的lineName被设计为使用文本类型。现在我们需要根据这个字段进行聚合操作,那么runtime字段怎么用呢?5.实现5.1mappingPUT/index_script_fields{"mappings":{"properties":{"lineId":{"type":"keyword"},"lineName":{"type":"text"}}}}注意这个lineName的类型是text5.2插入数据PUT/index_script_fields/_bulk{"index":{"_id":1}}{"lineId":"line-01","lineName":"LineA"}{"index":{"_id":2}}{"lineId":"line-01","lineName":"LineA"}{"index":{"_id":3}}{"lineId":"line-02","lineName":"C线"}5.3。按行聚合从上面的映射中,lineName是text类型的,不能聚合。那么此时我们要进行聚合,就可以使用runtime字段来实现5.3.1不要使用运行时字段不要使用运行时字段5.3.2使用运行时字段5.3.2.1dslGET/index_script_fields/_search{"runtime_mappings":{"aggLineName":{"type":"keyword","script":“发出(params['_source']['lineName']+'new')”}},“查询”:{“match_all”:{}},“字段”:[“lineName”],“aggs”:{"agg_line_name":{"terms":{"field":"aggLineName","size":10}}}}5.3.2.2java代码@Test@DisplayName("lineName字段为文本类型,不能聚合.为聚合操作定义一个运行时字段")publicvoidtest01()throwsIOException{SearchRequestrequest=SearchRequest.of(searchRequest->searchRequest.index(INDEX_NAME)//查询所有data.query(query->query.matchAll(matchAll->matchAll))//runtimefield字段不会出现在_source中,需要使用fieldsapi获取fields(fields->fields.field("lineName"))//创建一个runtime字段字段类型是关键词.runtimeMappings("aggLineName",runtime->runtime//这里的字段类型是keyword.type(RuntimeFieldType.Keyword).script(script->script.inline(inline->//如果运行时使用无痛脚本语言field,你需要使用emitinline.lang(ScriptLanguage.Painless).source("emit(params['_source']['lineName']+'new')")))//aggregateoperation.aggregations("agg_line_name",agg->//这里的aggLineName就是上一步runtime字段的字段agg.terms(terms->terms.field("aggLineName").size(10)).size(100));System.out.println("请求:"+request);SearchResponseresponse=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.java7,参考链接1,https://www.elastic.co/guide/en/elasticsearch/reference/8.6/runtime.html