首页 > 其他分享 >elasticsearch中使用runtime fields

elasticsearch中使用runtime fields

时间:2023-02-01 22:44:58浏览次数:67  
标签:index lineName script fields field elasticsearch runtime

1、背景

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

2、runtime field介绍

2.1 runtime field可以实现的功能

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

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

2.2 runtime field优缺点

  1. runtime field是运行时增加的字段,不会被索引和存储,不会增加索引的大小。
  2. runtime field 可以像普通字段一样使用,可以进行查询,排序,聚合等操作。
  3. 可以动态的添加字段。
  4. 可以在查询时覆盖字段的值。即fields中和_source中可以返回同名的字段,但是值可能不一样。
  5. 阻止mapping爆炸,可以先使用后定义。
  6. 针对经常被搜索或聚合等操作的字段,不适合使用runtime field,而应该定义在mapping中。
  7. 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中可以lineNametext类型,是不可进行聚合操作的,那么此时我们想进行聚合操作,就可以使用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

标签:index,lineName,script,fields,field,elasticsearch,runtime
From: https://www.cnblogs.com/huan1993/p/17084355.html

相关文章

  • 在Runtime下,IL2CPP与Mono打包对应的PSS内存占用问题
    1)在Runtime下,IL2CPP与Mono打包对应的PSS内存占用问题​2)获得AssetBundle内部依赖关系的方法3)Unity2019StreamingMipmap在某些情况下采样等级错误4)根据RenderDoc的数据,计......
  • linux 安装 elasticsearch
    下载#注意下载版本cd/usr/local/srcwgethttps://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-5.4.0.tar.gz2、安装cd/usr/local/srctar-xvfelastics......
  • ElasticSearch实践分享
     背景介绍最近在做一个采购商城搜索的功能,核心功能是根据用户录入的关键字在商品库中根据全称匹配进行检索得到结果方案比较目标在不超过100万的数据集合中,根......
  • ElasticSearch 学习笔记
    ElasticSearch基础知识索引index一个索引就是一个拥有几分相似特征的文档的集合。索引就类似于关系型数据库中的库的概念。类型type一个类型是索引中的一......
  • Elasticsearch 从入门到实践 小册笔记
    MappingJSON中是可以嵌套对象的,保存对象类型可以用object类型,但实际上在ES中会将原JSON文档扁平化存储的。假如作者字段是一个对象,那么可以表示为:{"author":{......
  • Springboot 中 Elasticsearch 使用
    项目中所使用代码已开源:​​https://gitee.com/szwei/elasticsearch​​项目中使用依赖版本:依赖版本spring-boot2.3.1.RELEASEelasticsearch7.9.3-windows-x86_64kibana7......
  • ElasticSearch概念与架构原理
    一、概述ElasticSearch简介简介ES是建立在Lucene基础之上的分布式准实时搜索引擎,它所提供的诸多功能中有一大优点,就是实时性好。比如:在业务需求中,新增数据需要1min才......
  • Elasticsearch基础操作
    一、索引操作创建索引创建索引时根据需求对索引设置主分片和副分片的数量,请求类型为:put,示例代码如下:PUT/${index_name}{"settings":{.........
  • 导入ElasticSearch官方测试数据
    学习ES的过程中,苦于测试数据不全,手动插入数据速度太慢,后来发现ES官方提供了一些测试数据可以直接导入到自建的ES,但是由于官方文档的没有更新,导入过程中会报错,具体原因是E......
  • 在elasticsearch中简单的使用script_fields
    目录1、背景2、准备数据2.1mapping2.2插入数据3、案例3.1格式化性别1-男2-女-1-未知如果不存在sex字段,则显示--其余的显示**3.1.1dsl3.1.2java代码3.1.3运行结......