【Elasticsearch】es脚本编程使用详解

news2024/12/29 14:12:03

目录

一、es脚本语言介绍

1.1 什么是es脚本

1.2 es脚本支持的语言

1.3 es脚本语言特点

1.4 es脚本使用场景

二、环境准备

2.1 docker搭建es过程

2.1.1 拉取es镜像

2.1.2 启动容器

2.1.3 配置es参数

2.1.4 重启es容器并访问

2.2 docker搭建kibana过程

2.2.1 拉取kibana镜像

2.2.2 启动kibana容器

2.2.3 修改配置文件

2.2.4 重启容器并访问

三、Scripting 使用详解

3.1 数据准备

3.1.1 创建索引

3.1.2 添加测试数据

3.2 es脚本常用CRUD操作

3.2.1 修改id为1001数据的价格

3.2.2 修改id为1005数据的tag

3.2.3 删除id为1005数据

3.2.4 upsert操作

3.2.5 使用expression查询

3.3 参数化脚本使用

3.3.1 修改1005这条数据的字段值

3.3.2 对字段值进行计算

3.3.3 对字段值进行计算并输出多个结果

3.4 参数化脚本的存储

3.4.1 自定义一个参数脚本

3.4.2 查询脚本模板

3.4.3 使用自定义脚本模板

四、Scripting 函数式编程

4.1 函数式编程格式

4.2 函数式编程使用

4.2.1 同时操作多个字段

4.2.2 条件表达式

4.2.3 数据统计与聚合

五、写在文末


一、es脚本语言介绍

1.1 什么是es脚本

Elasticsearch的 Scripting 是es支持的一种专门用于复杂场景下实现可编程的强大脚本功能。通过Scripting 脚本编程,可以实现更复杂的查询、数据处理、数据定制统计聚合以及柔性调整索引结构等。

1.2 es脚本支持的语言

es支持多种脚本语言,比如Painless,这是 Elasticsearch 自家开发的一种安全、高效并且易于学习的语言,其语法与Java很类似,编程中,也有注释、关键字、类型、变量、函数等,相较于其他支持的脚本语言性能更高,并且安全可靠,可以用于内联和存储脚本。

除了 Painless,Elasticsearch 也支持其他几种脚本语言,如 Lucene 的表达式语言,但 Painless 是推荐和默认的选项。具体来说,常用的支持语言如下:

  • groovy,ES1.4X~5.0默认的脚本语言;

  • Painless,JavaEE使用java语言开发,.net使用C#语言开发,Flutter使用Dart语言开发,ES5.X之后的Scripting 使用的默认语法就是Painless,Painless是一种专门用于es的脚本语法,是ES5.0+的默认脚本语言,其语法与Java很类似;

  • expression:每个文档的开销较低,表达式的作用更多,可以非常快速地执行,甚至比编写native脚本还要快,支持javascript语法的子集。缺点:只能访问数字,布尔值,日期和geo_point字段,存储的字段不可用;

  • mustache:提供模板参数化查询。

1.3 es脚本语言特点

使用es脚本语言进行编程具有如下特点

  • 语法简单,学习成本较低;

  • 灵活度高,可编程能力强;

  • 性能相对于其他脚本语言高;

  • 安全性好;

  • 独立语言,虽然易学但是仍需单独学习;

  • 相较于DSL语言性能低;

  • 不适用于复杂的业务场景;

1.4 es脚本使用场景

在下面的一些场景下可以考虑使用es脚步。

计算字段

你可以使用脚本在查询时动态地改变或添加字段的值,这对于数据分析的场景下具有重要的作用。 

脚本查询

在查询中使用脚本进行复杂的条件判断。es脚本语言很灵活,其中painless类型下,其语法格式和java非常相似,支持各类条件查询。 

脚本聚合

使用脚本进行更复杂的聚合计算。 

二、环境准备

为了后面的操作和演示方便,使用docker 快速搭建起es的操作环境。

搭建的服务包括 es+kibana。使用的版本为7.6.2.

2.1 docker搭建es过程

2.1.1 拉取es镜像

docker pull elasticsearch:7.6.2

2.1.2 启动容器

使用下面的命令启动es的容器

docker run -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms512m -Xmx512m" --name es7.6 -d elasticsearch:7.6.2

重点需要注意这个配置,ES_JAVA_OPTS="-Xms512m -Xmx512m",这个配置参数的值最好根据你的服务器配置来决定,一般最好不要低于512m即可;

2.1.3 配置es参数

进入到es容器内部,然后找到下面的这个文件

然后将下面的配置参数配置进去

cluster.name: "docker-cluster"
http.cors.enabled: true
network.host: 0.0.0.0
http.port: 9200
http.cors.allow-origin: "*"

2.1.4 重启es容器并访问

配置完成后重启docker容器,重启成功后,开放9200的端口,然后浏览器可以访问IP:9200,看到如下信息,说明es的搭建完成

2.2 docker搭建kibana过程

2.2.1 拉取kibana镜像

为了减少后面的配置麻烦和一些问题,建议kibana版本与es版本一致

docker pull kibana:7.6.2

2.2.2 启动kibana容器

这里的IP,如果是云服务器,注意使用内网的IP地址

docker run --name kibana -e ELASTICSEARCH_HOSTS=http://es服务IP:9200 -p 5601:5601 -d kibana:7.6.2

2.2.3 修改配置文件

进入到kibana容器中,进入到下面的目录中

cd /usr/share/kibana/config
vi kibana.yml 

将如下的配置信息配置进去(es的IP地址如果是云服务器建议使用内网IP)

server.name: kibana
server.host: "0"
elasticsearch.hosts: [ "http://es服务IP:9200" ]
xpack.monitoring.ui.container.elasticsearch.enabled: true
i18n.locale: zh-CN

2.2.4 重启容器并访问

上述配置信息配置完成后,重启容器,开放5601端口,浏览器就可以直接访问,IP:5601,看到下面的效果说明kibana搭建完成

三、Scripting 使用详解

3.1 数据准备

3.1.1 创建索引

使用下面的语句创建一个book的索引

PUT books

3.1.2 添加测试数据

添加如下测试数据

PUT /books/_doc/1001
{
  "id":"1001",
  "title":"Java technology fans",
  "category":"Java",
  "price":129,
  "from":"shanghai"
}

PUT /books/_doc/1002
{
  "id":"10034",
  "title":"Python data analysis",
  "category":"Python",
  "price":98,
  "from":"hangzhou",
  "tags":["python","analysis"]
}

PUT /books/_doc/1003
{
  "id":"1003",
  "title":"Js vue",
  "category":"web",
  "price":68,
  "from":"wuhan",
  "barcode":["js","web"]
}

PUT /books/_doc/1004
{
  "id":"1004",
  "title":"Mysql dba",
  "category":"mysql",
  "price":88,
  "from":"hangzhou",
  "barcode":["mysql","analysis"]
}

PUT /books/_doc/1005
{
  "id":"1005",
  "title":"Python official ",
  "category":"Python",
  "price":108,
  "from":"hangzhou",
  "barcode":["python","analysis"]
}

测试其中一条添加数据效果

全部添加之后,可以检查下是否添加成功

3.2 es脚本常用CRUD操作

操作语法

ctx._source.<field-name>

参数说明

  • ctx,表示当前操作对象的上下文环境;

  • _source,表示包裹数据对象的标识;

  • field-name,具体操作的某个字段

3.2.1 修改id为1001数据的价格

将id为1001的数据的价格加1元,操作语法如下

POST /books/_update/1001
{
  "script": {
    "source": "ctx._source.price+=1"
  }
}

操作完成后,再次查看这条数据,发现价格加1了

上面的语法也可以简写为下面这样

POST /books/_update/1001
{
  "script": "ctx._source.price+=1"
}

3.2.2 修改id为1005数据的tag

给id为1005的这条数据中的barcode字段的值再增加一个service的值

执行下面的语句

POST /books/_update/1005
{
  "script": {
    "lang": "painless", 
    "source": "ctx._source.barcode.add('service')"
  }
}

执行完成后再次查询,可以看到barcode中就多了一个service的值

3.2.3 删除id为1005数据

执行下面的语句进行数据删除

POST /books/_update/1005
{
  "script": {
    "lang": "painless", 
    "source": "ctx.op='delete'"
  }
}

执行完成后再次查询这条数据,已经查不到了

3.2.4 upsert操作

upsert为更新或新增,当操作的这条数据不存在的时候,执行新增;如果已存在,则执行修改操作,以上面的1005这条被删除的数据,当执行下面的语句时,由于1005不存在,所以会新增一条数据,而其他已存在的数据的price会加10;

POST /books/_update/1005
{
  "script": {
    "lang": "painless", 
    "source": "ctx._source.price += 10"
  },
  "upsert": {
    "id":"1005",
    "title":"Python official ",
    "category":"Python",
    "price":108,
    "from":"hangzhou",
    "barcode":["python","analysis"]
  }
}

执行上面的语句之后,查询一下看到新增了一条100的数据

如果再执行一次,通过右侧执行结果,这一次就是修改操作了

3.2.5 使用expression查询

在上文讲到,es5之后默认的脚本语言是Painless,在某些场景下也可以使用expression来操作,注意的是,使用expression类型查询时,语法格式将有所变化,需要以script_fields开头,这个在kibana中会有提示,如下为查询数据的price字段的值

GET /books/_search
{
  "script_fields": {
    "get_price": {
      "script": {
        "lang": "expression",
        "source": "doc['price'].value"
      }
    }
  }
}

也可以基于某个值进行计算操作,比如将price的值*10

3.3 参数化脚本使用

在很多编程语言中都支持外部参数的传入,在es的painless脚本编程中,也支持参数化使用,参数化脚本可以让脚本程序的灵活性和可扩展性更好。

3.3.1 修改1005这条数据的字段值

比如在上面的案例中,为id为1005的这条数据的barcode字段中添加一个service的值,如果使用参数化的方式来做,可以修改为下面这样

POST /books/_update/1005
{
  "script": {
    "lang": "painless", 
    "source": "ctx._source.barcode.add(params.barcode_name)",
    "params":{
      "barcode_name":"service"
    }
  }
}

执行上面的语句之后再次查询这条数据,barcode字段中就多了一个service的值

3.3.2 对字段值进行计算

使用下面的这段脚本对price进行计算

GET /books/_search
{
  "script_fields": {
    "get_price": {
      "script": {
        "lang": "painless",
        "source": "doc['price'].value * params.num",
        "params":{
          "num":10
        }
      }
    }
  }
}

得到如下结果

当然也可以使用expression来做,执行语句如下

GET /books/_search
{
  "script_fields": {
    "get_price": {
      "script": {
        "lang": "expression",
        "source": "doc['price'].value * num",
        "params":{
          "num":10
        }
      }
    }
  }
}

3.3.3 对字段值进行计算并输出多个结果

也可以自定义多个参数,根据需要输出多个参数的计算结果值,如下,为一个书本打折扣的场景,分别输出在9折,8折,7折下的价格

GET /books/_search
{
  "script_fields": {
    "get_price": {
      "script": {
        "lang": "painless",
        "source": "[doc['price'].value * params.num_9,doc['price'].value * params.num_8,doc['price'].value * params.num_7]",
        "params":{
          "num_9":0.9,
          "num_8":0.8,
          "num_7":0.7
        }
      }
    }
  }
}

执行结果如下

3.4 参数化脚本的存储

有些脚本可能在后续经常被使用到,就可以考虑将这些脚本存储到es的内存中,这就有点像mysql中的存储过程或函数一样。下面来看具体的操作流程。

3.4.1 自定义一个参数脚本

自定义如下参数化脚本

# 语法格式,_scripts/{script_id}
POST _scripts/caculate_price
{
   "script": {
    "lang": "painless", 
    "source": "doc.price.value * params.discount"
  }
}

执行之后,将会在内存中存储一个参数化脚本的模板

3.4.2 查询脚本模板

使用下面的语句可以查询内存中存储的脚本模板

3.4.3 使用自定义脚本模板

在查询数据的时候,为了计算折扣后的值,就可以直接使用上面定义的脚本模板

GET /books/_search
{
  "script_fields": {
    "discount_price": {
      "script": {
        "id":"caculate_price",
        "params":{
          "discount":0.9
        }
      }
    }
  }
}

得到如下的结果

四、Scripting 函数式编程

在上文通过实际案例演示了使用es的脚本编程的能力,细心的同学会发现,其实在上面的操作中,都是针对一些比较简单的场景进行使用,大多数基本上一行代码搞定,如果是更复杂的操作呢?比如既要更新字段的数据,同时也要对对数据进行计算等更复杂的操作呢,这时候就需要使用Scripting 的函数式编程了。官方文档地址: 官方文档

4.1 函数式编程格式

以上面的某个案例为例,如下是对1005数据的字段进行修改

POST /books/_update/1005
{
  "script": {
    "lang": "painless", 
    "source": "ctx._source.barcode.add(params.barcode_name)",
    "params":{
      "barcode_name":"service"
    }
  }
}

如果使用函数式编程的,在上面的脚本中,需要对 source这里做如下调整,即source后面的表达式使用3个引号包裹起来,如下所示

POST /books/_update/1005
{
  "script": {
    "lang": "painless", 
    "source": 
    """
    	ctx._source.barcode.add(params.barcode_name)
    """,
    "params":{
      "barcode_name":"caculate"
    }
  }
}

那么在做业务编码时,只需在3个引号中做即可,执行上面的脚本,效果类似

4.2 函数式编程使用

进入es官方文档:https://www.elastic.co/guide/en/elasticsearch/painless/7.10/painless-lang-spec.html ​​​​​​​,可以看到更多关于函数式编程的操作使用,可以结合这些示例进行使用,比如在官方文档中看到可以支持更多的语法,像if,try等

下面结合上述的books这个索引中的相关数据进行操作说明

4.2.1 同时操作多个字段

对当前索引中的id为1005的数据price值+10,同时给每条数据的barcode添加一个新的标签mark,参考如下的语句;

POST /books/_update/1005
{
  "script": {
    "lang": "painless", 
    "source": 
    """
    	ctx._source.barcode.add(params.barcode_name);
    	ctx._source.price += 10
    """,
    "params":{
      "barcode_name":"mark"
    }
  }
}

检查是否执行成功

4.2.2 条件表达式

在script脚本中,也支持对条件表达式的使用,比如在某些情况下需要结合业务对字段进行判断,就可以使用if来处理,如下,是对1005这条数据的操作

POST /books/_update/1005
{
  "script": {
    "lang": "painless", 
    "source": 
    """
    	if(ctx._source.price > 100){
    	  ctx._source.price = 100;
    	}
    	
    """,
    "params":{
      "barcode_name":"mark"
    }
  }
}

执行成功后,确认数据是否修改成功

4.2.3 数据统计与聚合

统计数据中price大于100的数据,如下

GET /books/_search
{
  
  "aggs": {
    "big100_total_count": {
      "cardinality": {
        "script": {
          "source":
           
           """
            if(doc['price'].value < 100) { return null ; } else { return  doc['_id'].value}
           """
           ,
           "lang": "painless"
        }
      }
    }
  }
}

执行结果如下,当前查到了2条数据

五、写在文末

es脚本编程在某些特殊的场景下可以发挥很大的用场,也算是es众多高级功能中一个重要的组成部分,合理使用es的脚步语言编程,可以给实际工作带来意想不到的效果,感兴趣的同学可以深入学习。

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

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

相关文章

crossover23.6闪亮登场发布啦,2023最新功能解析

CrossOver刚刚更新了23.6版本&#xff0c;新增了多款游戏的支持&#xff0c;快来看看你想玩的游戏在不在里面吧。点击这里立即下载最新版CrossOver。 软件介绍 CrossOver 23.6 让Mac可以运行Windows程序的工具 已通过小编安装运行测试 100%可以使用。 CrossOver for Mac 23.…

手把手教你玩转单目摄像头(OpenCv+Python)

目录 ​编辑 一&#xff0c;单目应用前景 二&#xff0c;打开摄像头 三&#xff0c;设置分辨率 四&#xff0c;摄像头拍照 五&#xff0c;录制视频 六&#xff0c;单目结合OpenCV的实际应用 一&#xff0c;单目应用前景 单目视觉&#xff08;monocular vision&#xff0…

C++入门03——程序流程结构

C/C支持最基本的三种程序运行结构&#xff1a;顺序结构、选择结构、循环结构 顺序结构&#xff1a;程序按顺序执行&#xff0c;不发生跳转 选择结构&#xff1a;依据条件是否满足&#xff0c;有选择的执行相应功能 循环结构&#xff1a;依据条件是否满足&#xff0c;循环多次…

Leetcode刷题详解——寻找旋转排序数组中的最小值

1. 题目链接&#xff1a;153. 寻找旋转排序数组中的最小值 2. 题目描述&#xff1a; 已知一个长度为 n 的数组&#xff0c;预先按照升序排列&#xff0c;经由 1 到 n 次 旋转 后&#xff0c;得到输入数组。例如&#xff0c;原数组 nums [0,1,2,4,5,6,7] 在变化后可能得到&…

通俗介绍:什么是 Redis ?

刚接触 Redis 的伙伴们可能会因为不熟悉而感到困惑。本文简述 Redis 是什么、有哪些作用的问题&#xff0c;是一篇短浅而入门级别的文章。 Redis官网&#xff1a;Redis 打开 Redis 官网可以看到&#xff0c;官方对 Redis 的介绍是这样的&#xff1a;The open source, in-memo…

win10安装spark

一、进入spark下载页面 连接 Downloads | Apache Spark 二、解压下载后的.tgz文件 直接解压即可 三、运行 运行bin目录下的 spark-shell.cmd 提示 Did not find winutils.exe: java.io.FileNotFoundException: java.io.FileNotFoundException: HADOOP_HOME and hadoop.hom…

如何理解某一个开发框架的意图,从而去写和落代码文件位置不会出错

理解一个开发框架的意图并正确地组织代码和文件位置是一个重要的技能。这不仅需要对框架本身有深入的理解&#xff0c;还需要对框架背后的设计哲学和最佳实践有所了解。以下是一些帮助你达到这一目标的步骤和建议&#xff1a; 1. 学习框架的文档 详细阅读: 开始使用任何框架前…

基于Java的学生学籍管理系统设计与实现(源码+lw+部署文档+讲解等)

文章目录 前言具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序&#xff08;小蔡coding&#xff09; 代码参考数据库参考源码获取 前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作者&am…

智慧矿山:AI算法助力!刮板机监测,生产效率和安全性提升!

工作面刮板机在煤矿等采矿场景中起着重要作用。为了提高其生产效率和安全性&#xff0c;研究人员开发了一种基于 AI 算法的刮板机监测技术。 在传统的刮板机监测中&#xff0c;通常需要人工观察和判断刮板机的状态。这种方法存在许多问题&#xff0c;如主观性、耗时和易出错等。…

MobileNetV3

相对重量级网络而言&#xff0c;轻量级网络的特点是参数少、计算量小、推理时间短。更适用于存储空间和功耗受限的场景&#xff0c;例如移动端嵌入式设备等边缘计算设备。因此轻量级网络受到了广泛的关注&#xff0c;其中MobileNet可谓是其中的佼佼者。MobileNetV3经过了V1和V2…

C++简单实现内存池原理

前言 该代码仅用于学习和理解其原理&#xff0c;当然高效内存池肯定是需要算法的。 // demo.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。 //#pragma pack(1) #include <iostream> using namespace std; //简单内存池 class gril { public…

国产内存强势崛起,光威龙武挑战D5内存24×2新标杆

今年国产内存的表现非常亮眼&#xff0c;出现了很多高质量的普惠产品&#xff0c;像是最近光威推出的一款内存条龙武ddr5 242就很有竞争力&#xff0c;加上之前神策新加入的ddr5 242版本&#xff0c;都是备受瞩目的新品&#xff0c;凭实力把DIY主机的内存配置拉高到了48GB。 龙…

Python遍历删除列表元素的一个奇怪bug

假定有一个Python列表&#xff0c;比如[CFFEX.IF, CFFEX.TS,SHFE.FU]&#xff0c;现在需要将其中带‘CFFEX’前缀的所有元素都删除。在使用列表推导式一行代码搞定之前&#xff0c;用了一种最朴素的遍历删除方法&#xff0c;结果出现了意想不到的的问题。复盘了下&#xff0c;结…

【带头学C++】----- 1.基础知识 ---- 1.23 运算符概述

1.23 运算符概述 运算符&#xff0c;在数学中常见的加减乘除之类的符号&#xff0c;那么在C在编程语言中呢&#xff0c;将使用特定的符号或标记对操作数进行操作以生成结果。用算术运算符将运算对象(也称操作数)连接起来的、符合C 语法规则的式子&#xff0c;称为C 算术表达式运…

配置Sentinel 控制台

1.遇到的问题 服务网关 | RuoYi 最近调试若依的微服务版本需要用到Sentinel这个组件&#xff0c;若依内部继承了这个组件连上即用。 Sentinel是阿里巴巴开源的限流器熔断器&#xff0c;并且带有可视化操作界面。 在日常开发中&#xff0c;限流功能时常被使用&#xff0c;用…

《现代音乐人编曲手册_传统管弦乐配器和MIDI》 笔记

MIDI 已经广泛应用在音乐制作的各个领域&#xff0c;但模仿传统管弦乐队的演奏仍是公认的 MIDI制作难点。很多制作者使用了庞大的采样音源&#xff0c;但仍然制作不出像样的管弦乐作品。即便是音乐专业出身、学习过传统管弦乐配器法的专业人士&#xff0c;也经常出现“谱面没问…

UGO+DRS评复之路

前言 针对数据库整体迁移方案&#xff0c;为解决异构平台数据库迁移&#xff0c;为减轻迁移人员的工作强度以及迁移周期。华为云GaussDB迁移UGO&DRS迁移工具应运而生。 UGO介绍 数据库和应用迁移&#xff08;Database and Application Migration UGO&#xff0c;简称为UG…

2 https原理

1 HTTPS与HTTP的区别&#xff1f;

Linux友人帐之日志与备份

一、日志 1.1概述 日志文件是重要的系统信息文件&#xff0c;其中记录了许多重要的系统事件&#xff0c;包括用户的登录信息、系统的启动信息、系统的安全信息、邮件相关信息、各种服务相关信息等。日志对于安全来说也很重要&#xff0c;它记录了系统每天发生的各种事情&#…

【lesson1】数据库基础

文章目录 连接数据库服务器什么是数据库初步见识数据库 连接数据库服务器 指令&#xff1a; -h&#xff1a;指明登入部署了MySQL服务的主机 -P&#xff1a;指明我们要访问的端口号 -u&#xff1a;指明登入用户 -p&#xff1a;指明需要输入密码 什么是数据库 在Linux查看具…