在elasticsearch中简单的使用script_fields

news2024/12/29 8:20:00

文章目录

  • 1、背景
  • 2、准备数据
    • 2.1 mapping
    • 2.2 插入数据
  • 3、案例
    • 3.1 格式化性别 1-男 2-女 -1-未知 如果不存在sex字段,则显示-- 其余的显示 **
      • 3.1.1 dsl
      • 3.1.2 java代码
      • 3.1.3 运行结果
    • 3.2 判断用户是否有某个爱好
      • 3.2.1 dsl
      • 3.2.2 java代码
      • 3.2.3 运行结果
    • 3.3 统计湖北的用户有几个
      • 3.3.1 dsl
      • 3.3.2 java代码
      • 3.3.3 运行结果
  • 4、doc[..]和params[_source][..]有何不同
  • 5、完整代码
  • 6、参考文档

1、背景

在我们使用es时,有些时候需要动态返回一些字段,而这些字段是通过动态计算得出的,那么此时该如何操作呢? 比如:我们索引中有一个sex字段,保存的是1或0,而在页面上需要展示,那么这个时候就可以使用script_fields来解决。可能有些人说,我通过后台进行格式化一下不就行了吗,但是假设我们需要在kibana等可视化工具上展示呢?

2、准备数据

2.1 mapping

PUT /index_script_fields
{
  "mappings": {
    "properties": {
      "name":{
        "type": "keyword"
      },
      "sex":{
        "type": "integer"
      },
      "hobbies":{
        "type":"keyword"
      },
      "address":{
        "properties": {
          "province":{
            "type":"keyword"
          },
          "city":{
            "type":"keyword"
          }
        }
      }
    }
  }
}

注意:

  1. hobbies其实是一个数组类型
  2. address是一个Object类型,即是一个复杂类型

2.2 插入数据

PUT /index_script_fields/_bulk
{"index":{"_id":1}}
{"name":"张三","sex":1,"hobbies":["足球","篮球"],"address":{"province":"湖北","city":"city01"}}
{"index":{"_id":2}}
{"name":"张三","sex":2,"address":{"province":"北京","city":"city01"}}
{"index":{"_id":3}}
{"name":"张三","hobbies":["足球"],"address":{"province":"湖北","city":"city01"}}

注意:

  1. 需要注意一下id=3的数据是没有sex属性的,那么在painless脚本中如何保证不报错。

3、案例

3.1 格式化性别 1-男 2-女 -1-未知 如果不存在sex字段,则显示-- 其余的显示 **

3.1.1 dsl

GET /index_script_fields/_search
{
  "query": {
    "match_all": {}
  },
  "_source": ["*"], 
  "script_fields": {
    "sex_format": {
      "script": {
        "lang": "painless",
        "source": """
          
          // 判断 sex 字段是否存在
          if(doc['sex'].size() == 0){
            return "--";
          }
        
          if(doc['sex'].value == 1){
            return "男";
          }else if(doc['sex'].value == 2){
            return "女";
          }else if(doc['sex'].value == -1){
            return "未知";
          }else{
            return "**";
          }
        """
      }
    }
  }
}

需要注意 sex 字段不存在,该如何判断,见上方的代码

3.1.2 java代码

@Test
@DisplayName("格式化性别 1-男 2-女 -1-未知 如果不存在sex字段,则显示-- 其余的显示 **")
public void test01() throws IOException {
    SearchRequest request = SearchRequest.of(searchRequest ->
            searchRequest.index(INDEX_NAME)
                    .query(query -> query.matchAll(matchAll -> matchAll))
                    // 不加这句,则 _source 不会返回,值返回 fields
                    .source(config -> config.filter(filter -> filter.includes("*")))
                    .scriptFields("sex_format", field ->
                            field.script(script ->
                                    script.inline(inline ->
                                            inline.lang(ScriptLanguage.Painless)
                                                    .source(" // 判断 sex 字段是否存在\n" +
                                                            "          if(doc['sex'].size() == 0){\n" +
                                                            "            return \"--\";\n" +
                                                            "          }\n" +
                                                            "        \n" +
                                                            "          if(doc['sex'].value == 1){\n" +
                                                            "            return \"男\";\n" +
                                                            "          }else if(doc['sex'].value == 2){\n" +
                                                            "            return \"女\";\n" +
                                                            "          }else if(doc['sex'].value == -1){\n" +
                                                            "            return \"未知\";\n" +
                                                            "          }else{\n" +
                                                            "            return \"**\";\n" +
                                                            "          }")
                                    )
                            )
                    )
                    .size(100)
    );

    System.out.println("request: " + request);
    SearchResponse<Object> response = client.search(request, Object.class);
    System.out.println("response: " + response);
}

3.1.3 运行结果

运行结果

3.2 判断用户是否有某个爱好

3.2.1 dsl

GET /index_script_fields/_search
{
  "_source": ["*"], 
  "query": {"match_all": {}},
  "script_fields": {
    "has_hobby": {
      "script": {
        "lang": "painless",
        "source": """
          // 没有hobbies字段,直接返回 false
          if(doc['hobbies'].size() == 0){
            return false;
          }
          return doc['hobbies'].indexOf(params.hobby) > -1;
        """,
        "params": {
          "hobby":"篮球"
        }
      }
    }
  }
}

3.2.2 java代码

@Test
@DisplayName("判断用户是否有某个爱好")
public void test02() throws IOException {
    SearchRequest request = SearchRequest.of(searchRequest ->
            searchRequest.index(INDEX_NAME)
                    .query(query -> query.matchAll(matchAll -> matchAll))
                    // 不加这句,则 _source 不会返回,值返回 fields
                    .source(config -> config.filter(filter -> filter.includes("*")))
                    .scriptFields("has_hobby", field ->
                            field.script(script ->
                                    script.inline(inline ->
                                            inline.lang(ScriptLanguage.Painless)
                                                    .source(" // 没有hobbies字段,直接返回 false\n" +
                                                            "          if(doc['hobbies'].size() == 0){\n" +
                                                            "            return false;\n" +
                                                            "          }\n" +
                                                            "          return doc['hobbies'].indexOf(params.hobby) > -1;")
                                                    .params("hobby", JsonData.of("篮球"))
                                    )
                            )
                    )
                    .size(100)
    );

    System.out.println("request: " + request);
    SearchResponse<Object> response = client.search(request, Object.class);
    System.out.println("response: " + response);
}

3.2.3 运行结果

运行结果

3.3 统计湖北的用户有几个

3.3.1 dsl

GET /index_script_fields/_search
{
  "query": {"match_all": {}}, 
  "aggs": {
    "agg_province": {
      "sum": {
        "script": {
          "lang": "painless",
          "source": """
            // 因为 address 是一个复杂类型,因此不可直接通过 doc 来访问
            if(params['_source']['address']['province'] == '湖北'){
              return 1;
            }
            return 0;
          """
        }
      }
    }
  }
}

因为 address 是一个复杂类型,因此不可直接通过 doc 来访问,只能通过 params[_source]来访问

3.3.2 java代码

@Test
@DisplayName("统计湖北省下的用户有几个")
public void test03() throws IOException {
    SearchRequest request = SearchRequest.of(searchRequest ->
            searchRequest.index(INDEX_NAME)
                    .query(query -> query.matchAll(matchAll -> matchAll))
                    // 不加这句,则 _source 不会返回,值返回 fields
                    .source(config -> config.filter(filter -> filter.includes("*")))
                    .aggregations("agg_province", agg->
                            agg.sum(sum ->
                                    sum.script(script ->
                                            script.inline(inline ->
                                                    inline.lang(ScriptLanguage.Painless)
                                                            // 因为 address 是一个复杂类型,因此不可直接通过 doc 来访问, 只可通过 params['_source']来访问
                                                            .source("// 因为 address 是一个复杂类型,因此不可直接通过 doc 来访问\n" +
                                                                    "            if(params['_source']['address']['province'] == '湖北'){\n" +
                                                                    "              return 1;\n" +
                                                                    "            }\n" +
                                                                    "            return 0;")
                                            )
                                    )
                            )
                    )
                    .size(100)
    );

    System.out.println("request: " + request);
    SearchResponse<Object> response = client.search(request, Object.class);
    System.out.println("response: " + response);
}

3.3.3 运行结果

![运行结果![](https://img-blog.csdnimg.cn/5910495ac0814db393125dae96934e38.png)

4、doc[…]和params[_source][…]有何不同

通过上面的案例,我们发现,我们有些时候是通过doc[..]来访问属性的,有些时候是通过params['_source'][..]来访问,那么这2种访问方式有何不同呢?

doc[..]:使用doc关键字,将导致该字段的术语被加载到内存(缓存),这将导致更快的执行,但更多的内存消耗。此外,doc[…]表示法只允许简单的值字段(您不能从中返回json对象),并且仅对非分析或基于单个术语的字段有意义。然而,如果可能的话,使用doc仍然是访问文档值的推荐方法。
params[_source][..]: 每次使用_source都必须加载和解析, 因此使用_source会相对而言要慢点。

虽然访问_source比访问doc values要慢,但是script_fields只对需要返回文档执行脚本,因此也不会太影响性能,除非返回的数据特别多。

在这里插入图片描述

5、完整代码

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

6、参考文档

1、https://www.elastic.co/guide/en/elasticsearch/reference/8.6/search-fields.html#script-fields

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/189923.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Oracle 程序被编译后自动增加了AUTHID CURRENT_USER授权

目录 背景 原因&#xff1a; 解决方法 背景 今天遇到一个大坑&#xff0c;新建的一个数据库用户调用apps下的程序包&#xff0c;程序反馈未授权无法使用。 但是DBA确认已经给了授权。 查询授权表也是有正确授权的&#xff0c;但就是显示无效授权。 后来debug进去&#x…

外汇k线图经典图解:穿头破脚

从事外汇、黄金交易怎么能不懂K线图&#xff0c;学看K线图怎么能不把一些经典图解铭记心中呢&#xff1f;它们就好比字典和工具书&#xff0c;当投资者在解读行情时遇到任何困惑&#xff0c;都能从这些经典中得到指引&#xff0c;从而指明自己的投资方向。今天&#xff0c;小编…

java ssm校园二手书交易平台idea

该网站从实际运用的角度出发&#xff0c;运用了计算机网站设计、数据库等相关知识&#xff0c;网络和Mysql数据库设计来实现的&#xff0c;网站主要包括学生注册、学生登录、浏览图书、搜索图书、查看图书并进行购买&#xff0c;对购买的图书进行确认收货、退款退货、查看个人信…

Elasticsearch连续剧之实战篇Java操作es

作者&#xff1a;狮子也疯狂 专栏&#xff1a;《es》 坚持做好每一步&#xff0c;幸运之神自然会驾凌在你的身上 目录一、&#x1f407;前言二、&#x1f407;原生JAVA操作ES_搭建项目Ⅰ、创建项目Ⅱ、索引操作2.1 创建空索引2.2 给索引添加结构2.3 删除索引Ⅲ、文档操作3.1 新…

vCloud删除OVDC网络时提示被vApp网络使用无法删除

环境 VMware Cloud Director 版本:10.3.2.19375051 现象 在vCloud租户视图删除OVDC网络,提示被vApp网络使用,无法删除。此时通过查看vApp发现并没有残留vApp网络。 解决办法 1、登录vCloud数据库: 登录方法可以参考:VMware Cloud Director数据库操作 2、查逻辑网络: …

CAN接口电路设计

CAN总线的全称是控制器局域网络&#xff0c;主要应用在汽车电子和工业控制领域。和485总线一样&#xff0c;CAN总线也是一种半双工的通信。一条CAN总线最多能接110个节点它最高速率能到1Mbps&#xff0c;最远传输距离能到10KMCAN总线有两个信号&#xff0c;一个是CANH&#xff…

如何在 Linux 命令行中优雅的格式化输出 xml,记住这三种方法!

xml&#xff08;可扩展标记语言&#xff09;也是一种人类可读的标记语言&#xff0c;但是如同 json 文件一样&#xff0c;没有缩进格式&#xff08;或者压缩&#xff09;的 xml 文件&#xff0c;读起来那是挺头疼的。 首先来看一下我们这篇文章要达到的目的&#xff0c;如下图…

代码随想录训练营第十七天|110.平衡二叉树 ● 257. 二叉树的所有路径 ● 404.左叶子之和

110.平衡二叉树 看完题后的思路 int[] f(root)if rootnull return [true,0]left[]f(root.left) if(!left[0]){return [false,-1]} right[]f(root.right) if(!right[0]){return [false,-1]} return[true,math.max(left[1],right[1])1] 思路 上面的过程弄复杂了&#xff0c;其…

Elasticsearch 入门到精通-Elasticsearch核心倒排索引数据结构

Elasticsearch 简介Elasticsearch 是一个分布式、高扩展、高实时的搜索与数据分析引擎。Elasticsearch 建立在全文搜索引擎 Apache Lucene™ 基础上&#xff0c;通过 Lucene 的倒排索引技术实现比关系型数据库更快的过滤&#xff0c;从而很方便的使大量数据具有搜索、分析和探索…

vue插槽之插槽的用法及作用域插槽详解

目录前言一&#xff0c;插槽的基本使用1.1 引出插槽1.2 插槽的基本使用1.3 默认插槽1.4 插槽样式二&#xff0c;具名插槽2.1 引出具名插槽2.2 具名插槽的使用三&#xff0c;template标签3.1 引出template标签3.2 template标签的使用四&#xff0c;作用域插槽4.1 引出作用域插槽…

C语言小题,有3个学生的信息,放在结构体数组中,要求输出全部学生的信息。(指向结构体数组的指针)

前言&#xff1a; 此篇是针对 指向结构体数组的指针 方面的练习。 解题思路&#xff1a; 用指向结构体变量的指针来处理&#xff1a; &#xff08;1&#xff09;声明结构体类型 struct Student &#xff0c;并定义结构体数组&#xff0c;同时使之初始化&#xff1b; &#xff…

【Rust】9. 常见集合

9.1 Vector 9.1.1 创建 vector vector 只能储存相同类型的值&#xff01;创建空的 vector&#xff1a;Vec::new()创建有值的 vector&#xff1a;vec! 宏 9.1.2 向 vector 中添加元素 9.1.3 读取 vector 的元素 索引语法&#xff1a;当引用一个不存在的元素时 Rust 会造成 pa…

设计模式-软件设计原则

目录 3.软件设计原则 3.1 开闭原则 3.2 里氏代换原则 3.3 依赖倒转原则 3.4 接口隔离原则 3.5 迪米特法则 3.6 合成复用原则 3.软件设计原则 在软件开发中&#xff0c;为了提高软件系统的可维护性和可复用性&#xff0c;增加软件的可扩展性和灵活性&#xff0c;程序员要…

【QT5 定时器练习-笔记-样例讲解-实现方式>>>(1)定时器事件方式和(2)定时器绑定函数】

QT5 -定时器简单应用-样例讲解-实现方式1-定时器事件方式1、前言2、实验环境3、定时器实现方式说明-以及效果3、操作步骤-&#xff08;1&#xff09;定时器事件方式&#xff08;1&#xff09;建立工程&#xff08;2&#xff09;拉控件布局&#xff08;3&#xff09;代码部分编写…

《深入浅出计算机组成原理》学习笔记 Day16

冒险和预测&#xff08;一&#xff09;1. 超长流水线的缺点2. 冒险和分支预测参考1. 超长流水线的缺点 增加流水线的深度&#xff0c;在同主频下&#xff0c;其实就是降低了 CPU 的性能。 一个 Pipeline Stage&#xff0c;就需要一个时钟周期。如果我们把任务分成 31 个阶段&…

2014年408专业算法题

文章目录0 结果1 题目2 思路附录0 结果 1 题目 2 思路 二叉树的带权路径长度&#xff08;WPL&#xff09;的计算方法有两种&#xff1a; 1&#xff0c;定义&#xff1a;WPL所有叶结点的权值Wi∗该结点深度Di求和WPL所有叶结点的权值W_i*该结点深度D_i求和WPL所有叶结点的权值…

如何管理IC研发过程产生的bug

一款芯片的研发过程中总是伴随着bug、bug和bug&#xff0c;研发线上各端的IC工程师也是全程在debug、debug和debug&#xff0c;直到最终的GDSII文件交给Founry工厂加工&#xff0c;全程都是为了保证芯片最终能够安全保质的tape-out成功。由此可见&#xff0c;bug的跟踪管理是至…

【数据结构】题解:二叉树的非递归遍历

【数据结构】题解&#xff1a;二叉树的非递归实现 文章目录【数据结构】题解&#xff1a;二叉树的非递归实现一、问题描述二、递归实现三、非递归实现3.1 前序遍历3.2 中序遍历3.3 后序遍历一、问题描述 二叉树的前序遍历&#xff0c;非递归迭代实现 &#xff0c;二叉树的前序遍…

Synology群晖小技巧之百度网盘远程下载同步

&#x1f388; 作者&#xff1a;互联网-小啊宇 &#x1f388; 简介&#xff1a; CSDN 运维领域创作者、阿里云专家博主。目前从事 Kubernetes运维相关工作&#xff0c;擅长Linux系统运维、开源监控软件维护、Kubernetes容器技术、CI/CD持续集成、自动化运维、开源软件部署维护…

[HCTF 2018]WarmUp1

http://ca039961-2ebb-4acd-8107-ece077539106.node4.buuoj.cn:81/ 按F12查看源码 根据提示访问source.php 分析源码&#xff0c;搞懂其中几个函数 mb_strpos() &#xff1a;返回要查找的字符串在要检查的字符串中首次出现的位置 mb_strpos (haystack ,needle) //haystack&…