首页 > 其他分享 >ES Scripts脚本相关

ES Scripts脚本相关

时间:2022-08-15 18:35:48浏览次数:104  
标签:脚本 script food doc Price painless source Scripts ES

Scripting是ES提供的一种支持自定义编程的用于复杂查询的脚本语言.主要用于复杂的计算,其类型主要有Painlessexpressions等等,下面开始分析,运行数据在ES 聚合查询中,自行查找.

 1、Reindex 数据备份

reindex 常用于数据备份,类似关系型数据库中的select * from tab1 into tab2,代码如下:

POST _reindex
{
  "source": {
    "index": "food"
  },
  "dest": {
    "index": "food_20220815"
  }
}

 

2、Painless

Painless脚本语言语法相对简单,灵活度高(一般情况下,基本上能解决任务问题,但是DSL也有其优势),安全性高,性能高(相对于其他脚本,但是其性能比DSL要低).不适用于非复杂业务,一般DSL能解决大部分的问题.解决不了的用类似Painless等脚本语言.

2.1 调整一条食物的价格,下调1元.

这里有两种方式,第一种是查到指定食物的当前价格,然后进行减1操作,通过update接口实现,代码如下:

POST food/_update/1
{
  "doc":{
    "Price":"11" //计算过后的值
  }
}

第二种就是通过script来解决了.类似于关系型数据库中的update table set field=field-1,代码如下:

POST food/_update/1
{
   "script": {
     "source": "ctx._source.Price-=1"
   }
}

这里ctx代表查询上下文,_source就是查询结果及hits中的_source.

这里第二种方式还有简写模式,代码如下:

POST food/_update/1
{
  "script": "ctx._source.Price-=1"
}

 

2.2 像Tags数组新增一个标签数据

和1.1中一样除了标准的dsl如下:

POST food/_update/1
{
  "doc": {
    "Tags":["性价比","营养","绿色蔬菜","新增的标签"]
  }
}

结果如下:

{
        "_index" : "food",
        "_id" : "1",
        "_score" : 1.0,
        "_source" : {
          "CreateTime" : "2022-06-06 11:11:11",
          "Desc" : "青菜 yyds 营养价值很高,很好吃",
          "Level" : "普通蔬菜",
          "Name" : "青菜",
          "Price" : 9.11,
          "Tags" : [
            "性价比",
            "营养",
            "绿色蔬菜",
            "新增的标签"
          ],
          "Type" : "蔬菜"
        }
      }

也可以通过以下Painless脚本来实现,代码如下:

POST food/_update/1
{
  "script": {
    "lang": "painless",
    "source": "ctx._source.Tags.add('新增的标签')"
  }
}

结果和DSL的结果一致.

 

2.3 删除一条数据

DSL代码如下:

DELETE food/_doc/66

painless脚本如下:

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

 

2.4 upsert 如果操作的数据存在则按照指定的脚本进行修改,如果不存在则新增一条数据

POST food/_update/66
{
  "script": {
    "lang": "painless",
    "source": "ctx._source.Price+=100"
  },
  "upsert": {
    "CreateTime": "2022-07-09 13:11:11",
    "Desc": "榴莲 非常好吃 很贵 吃一个相当于吃一只老母鸡",
    "Level": "高级水果",
    "Name": "榴莲",
    "Price": 100.11,
    "Tags": [
      "贵",
      "水果",
      "营养"
    ],
    "Type": "水果"
  }
}

自行构造数据,这里第一次执行,应为id为66的数据不存在所以走的新增操作,当第二次执行过后,执行的是painless脚本,对价格进行了100的追加.

 

4、Painless参数化脚本

参数化脚本类似于.Net程序中类似Dapper这类的Orm,在指定执行sql的同时在sql中定义查询参数,防止sql注入,在painless脚本中,参数化可以有效的解决脚本编译的问题,如2.2例子中,如果标签的内容发生变化,那es每次会编译执行脚本造成一定的性能影响。而如果使用参数化技术,则只会编译一次,避免性能浪费.

4.1 单个参数计算查询

还是商品折扣的例子,params.param1就是折扣参数

GET food/_search
{
  "script_fields": {
    "c_price": {
      "script": {
        "lang": "painless",
        "source": "doc['Price'].value * params.param1",
        "params": {
          "param1": 0.1
        }
      }
    }
  }
}

 

4.2 多个参数计算查询

GET food/_search
{
  "script_fields": {
    "c_price": {
      "script": {
        "lang": "painless",
        "source": "[doc['Price'].value * params.param1,doc['Price'].value * params.param2]",
        "params": {
          "param1": 0.1,
          "param2": 0.2
        }
      }
    }
  }
}

 

5、Painless 脚本模板

脚本模板类似于关系型数据库的存储过程,如果某些脚本需要查询功能需要在多个业务场景中使用,就可以使用脚本模板功能来满足需求.

POST _scripts/test_script_template
{
  "script":{
    "lang": "painless",
    "source": "doc.Price.value * params.param1"
  }
}

如上代码创建了一个功能为按照指定折扣返回价格的参数模板.下面是调用代码:

GET food/_search
{
  "script_fields": {
    "c_price": {
      "script": {
        "id":"test_script_template",
        "params": {
          "param1":0.1
        }
      }
    }
  }
}

 

6、expression 脚本

expression脚本有多种用处,这里分析其在计算字段的用途,计算字段不能使用ctx,而是要用doc

注意:

3.1 现在商场需要统计所有商品打八折之后的价格

GET food/_search
{
  "script_fields": 
  {
    "custom_price": {
      "script": {
        "lang": "expression",
        "source": "doc['Price'] * 0.8"
      }
    }
  }
}

这里可以也可以用painless脚本来实现,代码如下:

GET food/_search
{
  "script_fields": 
  {
    "custom_price": {
      "script": {
        "lang": "painless",
        "source": "doc['Price'].value * 0.8"
      }
    }
  }
}

执行结果包含如下错误如下:

"failures" : [
      {
        "shard" : 2,
        "index" : "food",
        "node" : "gfPxwY2JT9KPcf9J2uhszw",
        "reason" : {
          "type" : "script_exception",
          "reason" : "runtime error",
          "script_stack" : [
            "org.elasticsearch.index.fielddata.ScriptDocValues$Doubles.get(ScriptDocValues.java:209)",
            "org.elasticsearch.index.fielddata.ScriptDocValues$Doubles.getValue(ScriptDocValues.java:203)",
            "doc['Price'].value * 0.8",
            "            ^---- HERE"
          ],
          "script" : "doc['Price'].value * 0.8",
          "lang" : "painless",
          "position" : {
            "offset" : 12,
            "start" : 0,
            "end" : 24
          },
          "caused_by" : {
            "type" : "illegal_state_exception",
            "reason" : "A document doesn't have a value for a field! Use doc[<field>].size()==0 to check if a document is missing a field!"
          }
        }
      }
    ]

这是因为数据中包含Price为空的信息所以,才会报错.那么需要找到为空的相关信息,并更新掉.这里可以通过如下代码快速检索到Price为空的相关记录

GET food/_search
{
  "script_fields": 
  {
    "custom_price": {
      "script": {
        "lang": "painless",
        "source": "doc['Price'].size()<=0"
      }
    }
  }
}

结果中如下记录:

      {
        "_index" : "food",
        "_id" : "8",
        "_score" : 1.0,
        "fields" : {
          "custom_price" : [
            true
          ]
        }
      }

说明id为8的记录价格为空.更新完毕之后,再次执行painless计算字段脚本,结果和expression脚本一样.

 

 

 

 

 

 

 

 

标签:脚本,script,food,doc,Price,painless,source,Scripts,ES
From: https://www.cnblogs.com/GreenLeaves/p/16580826.html

相关文章

  • SpringBoot之RestController注解
    @RestController=@Controller+@RequestBody概念@RestController用过SpringMVC的人都知道,这个注解是加在类上面的,作用域是整个类,加上之后,这个类里面所有的接口......
  • Digester解析xml原理
    Tomcat内部是使用Digester来解析xml文件的,将xml转化为java对象。digester底层是基于SAX+事件驱动+栈的方式来搭建实现的,SAX主要用来解析xml,事件驱动主要是在解析的过程中......
  • 1 分钟在 Serverless 上部署现代化 Deno Web 应用
    简介: 利用Serverless的水平扩展与按量付费优势,结合自定义运行时,实现Web应用的快速迁移。作者|连喆人(掌上乾坤公司)本文选自“Serverless函数计算征......
  • mybatis_3_使用xml构建SqlSeesionFactory
    使用xml构建SqlSeesionFactory,分为两步:第一步:创建一个XML配置文件;第二步:创建SqlSessionFactory实例;示例:第一步:创建mybatis-config2.xml文件<?xmlversion="1.0"enco......
  • MicroSoft interview 2022 test1
    MicroSoftinterview2022test1Programingone点击查看代码defsolution(S,B):#writeyourcodeinPython(Python3.6)fixed=0holes=[]l......
  • Codeforces Round #813 (Div. 2) 题解A~E2
    https://codeforces.com/contest/1712估计也就我赛中才D都写不出来了A题题意:给你一个数组和一个正整数\(k\),每次可以选择数组的任意两个数交换,问你最少交换多少次能使......
  • unitest介绍
    unitest介绍UnitTest是Python自带的一个单元测试框架,用它来做单元测试unittest单元测试框架最早受到junit(junit是java的单元测试)的启发,和其他语言的主流单元测试框架有很......
  • Codeforces Round #813 (Div. 2)
    A.WonderfulPermutation题目描述God'sBlessingonThisPermutationForces!ARandomPebbleYouaregivenapermutationp_1,p_2,\ldots,p_noflengthnandapo......
  • Python 的 Requests 和 Httpx 在爬取应用中的一个区别
    HTTPX是功能齐全的Python3的HTTP客户端,支持同步和异步API,支持HTTP/1.1和HTTP/2。一般情况下,在爬取网页内容的时候,httpx与requests的基本使用方法几乎是一模一样的。......
  • sessionStorage的使用
    //保存数据到sessionStoragesessionStorage.setItem('key','value');//从sessionStorage获取数据letdata=sessionStorage.getItem('key');//从sessionSto......