ES中的script脚本操作
GET product2/_search
POST product2/_update/4
{
"script": {
"source": "ctx._source.price -=10"
}
}
#简写
POST product2/_update/4
{
"script": "ctx._source.price -=10;ctx._source.name += '程飞'"
}
GET product2/_doc/4
利用传参的方式,这样的效率更高,因为当你批量修改的时候,script代码只会编译一次
POST product2/_update/4
{
"script": {
"lang": "painless",
"source": "ctx._source.tags.add(params.tag_name)",
"params": {"tag_name":"无线充电"}
}
}
delete删除操作
GET product2/_doc/5
POST product2/_update/5
{
"script": {
"lang": "painless",
"source": "ctx.op='delete'"
}
}
upsert如果对应的id有数据,就直接update,如果没有,就用upsert的数据进行insert的操作
GET product2/_doc/4
POST product2/_update/4
{
"script": {
"lang": "painless",
"source": "ctx._source.price += params.par"
, "params": {
"par":100
}
},
"upsert": {
"name":"小米10",
"price":4999
}
}
正则表达式如果未启用 会报错,我们需要在配置文件elasticsearch.yml进行如下的配置 script.painless.regex.enabled: true
正则我们一般很少用,他的性能不好,而且会绕过 painless针对长时间运行和占用内存的脚本的保护措施,而且有深度堆栈行为
GET product2/_doc/1
POST product2/_update/1
{
"script": {
"lang": "painless",
"source": """
if(ctx_source.name =~ /[\s\S]*phone[\s\S]*/){
ctx._source.name += "***";
}else{
ctx.op = "noop";
}
"""
}
}
[0-9]{4}-[0-9]{2}-[0-9]{2}匹配出来的不一定是日期 比如 9999-99-99 但是日期一定能匹配上
=是模糊匹配,==是完全匹配
POST product2/_update/1
{
"script": {
"lang": "painless",
"source": """
if (ctx._source.createtime ==~ /[0-9]{4}-[0-9]{2}-[0-9]{2}/) {
ctx._source.name += "|***";
} else {
ctx.op = "noop";
}
"""
}
}
改成_bulk批量操作呢,_bulk是不能换行符的,不然会报错
GET product2/_doc/4
POST product2/_bulk
{
"update":{
"_id":4,
"retry_on_conflict":3
}
}
{
"script":{
"source":"ctx._source.price += params.par",
"lang":"painless",
"params":{"par":10000}
},
"upsert":{
"name":"红米旗舰版",
"price":15986
}
}
POST product2/_bulk
{"update":{"_id":4,"retry_on_conflict":3}}
{"script":{"source":"ctx._source.price += params.par","lang":"painless","params":{"par":10000}},"upsert":{"name":"红米旗舰版","price":15986}}
GET查询 除了painless(默认) ES还支持 (了解)
expression(快速的自定义排名和排序)
mustache(范本)
java(专家API)
这些语言应用场景更窄,但是可能性能更好
GET product2/_search
{
"script_fields": {
"test_field": {
"script": {
"lang": "expression",
"source": "doc['price']"
}
}
}
}
_search的script脚本操作,如果source中的字段没有,就会报错
GET product2/_search
GET product2/_search
{
"script_fields": {
"test_bala": {
"script": {
"lang": "painless",
"source": "doc['price'].value*9"
}
}
}
}
更换num的值 对比took消耗
doc['price'] * num只编译一次而doc['price'] * 9 会随着数字改变而一直编译,ES默认每分钟支持15次编译
GET product2/_search
{
"script_fields": {
"test_field": {
"script": {
"lang": "expression",
"source": "doc['price'] * num",
"params": {
"num": 6
}
}
}
}
}
例如 打8折价格
GET product2/_search
{
"script_fields": {
"chengfei": {
"script": {
"source": "doc.price.value*params.discount",
"params": {
"discount":0.8
}
}
}
}
}
原始价格 和 多个打折价格
GET product2/_search
{
"script_fields": {
"discount": {
"script": {
"source": "[doc['price'].value * params.discount_8,doc['price'].value * params.discount_7]"
, "params": {
"discount_8":0.8,
"discount_7":0.7
}
}
}
}
}
POST /product/_refresh
Stored scripts :可以理解为script模板 缓存在集群的cache中
/_scripts/{id} 类似存储过程 计算折扣 作用域为整个集群
默认缓存大小是100MB 没有过期时间 可以手工设置过期时间script.cache.expire 通过script.cache.max_size设置缓存大小 脚本最大64MB 通过script.max_size_in_bytes配置 只有发生变更时重新编译
这里设置的discount变量是让使用它的程序传入的,相当于是存储过程,或是函数
POST _scripts/bala1
{
"script":{
"lang": "painless",
"source": "doc['price'].value * params.discount"
}
}
GET _scripts/bala
GET product2/_search
{
"script_fields": {
"bala": {
"script": {
"id": "bala",
"params": {
"discount":0.5
}
}
}
}
}
Dates
官网Bug: 日期字段公开为 ZonedDateTime,因此它们支持诸如之类的方法getYear,getDayOfWeek 或例如从历元开始到毫秒getMillis。要在脚本中使用它们,请省略get前缀并继续使用小写的方法名其余部分。例如,以下代码返回每个冰球运动员的出生年份getYear()
getMonth()
getDayOfMonth()
getDayOfWeek()
getDayOfYear()
getHour()
getMinute()
getSecond()
getNano()
当然了前提是你的字段是时间类型是date的而且写法一定要是
GET product2/_search
PUT my_index2
{
"mappings": {
"properties": {
"name":{"type": "keyword"},
"create_time":{"type": "date"}
}
}
}
POST /my_index3/_bulk
{"index":{"_id":1}}
{"name":"chengfei","create_time":"2015-01-01T12:10:30Z"}
{"index":{"_id":2}}
{"name":"xuxu","create_time":"2015-01-01T18:10:30Z"}
GET /my_index3/_mapping
GET my_index/_search
GET /my_index3/_search
{
"script_fields": {
"date_test": {
"script": {
"source": "doc.create_time.value.hour"
}
}
}
}
下面的这种日期方法也行,只要是index插入的默认数据类型是date的都行,根据官网,这种日期写法确实也是date类型的,官网对于date类型的描述
POST /my_index4/_bulk
{"index":{"_id":1}}
{"name":"chengfei","create_time":"2015/01/01 23:50:30"}
{"index":{"_id":2}}
{"name":"xuxu","create_time":"2015/01/01 12:10:30"}
GET /my_index4/_mapping
GET my_index/_search
GET /my_index4/_search
{
"script_fields": {
"date_test": {
"script": {
"source": "[doc.create_time.value.minute,doc.create_time.value.dayOfWeek]"
}
}
}
}
那么遇到复杂脚本,写很多行怎么办呢
GET product2/_search
POST product2/_update/3
{
"script": {
"lang": "painless",
"source": """
ctx._source.name += params.name;
ctx._source.price -= params.price
""",
"params": {
"name":"无线充电宝",
"price":100
}
}
}
聚合查询的使用
统计所有价格小于1000商品tag的 数量 不考虑去重
GET product2/_search
{
"query": {
"bool": {
"filter": [
{"range": {
"price": {
"lt": 1000
}
}}
]
}
},
"aggs": {
"script_aggs_test": {
"terms": {
"field": "tags.keyword",
"size": 10
}
}
}
}
GET product/_search
{
"query": {
"bool": {
"filter": [
{"range": {
"price": {
"lt": 1000
}
}}
]
}
},
"aggs": {
"script_aggs_test": {
"sum": {
"script": {
"lang": "painless",
"source": """
int total = 0;
for (int i = 0 ;i<doc.tags.length;i++){
total ++
}
return total;
"""
}
}
}
}
}
以下为案件的嫌疑人信息
统计男性嫌疑人的数量
如果字段是复杂类型,如数组或是object的话,就不能直接用doc的方式,要用params._source的方式获取
GET test_index/_search
DELETE test_index
PUT test_index/_bulk?refres
{"index":{"_id":1}}
{"ajbh": "12345","ajmc": "立案案件","lasj": "2020/05/21 13:25:23","jsbax_sjjh2_xz_ryjbxx_cleaning": [{"XM": "张三","NL": "30","SF": "男"},{"XM": "李四","NL": "31","SF": "男"},{"XM": "王五","NL": "30","SF": "女"},{"XM": "赵六","NL": "23","SF": "男"}]}
{"index":{"_id":2}}
{"ajbh": "563245","ajmc": "结案案件","lasj": "2020/05/21 13:25:23","jsbax_sjjh2_xz_ryjbxx_cleaning": [{"XM": "张三2","NL": "30","SF": "男"},{"XM": "李四2","NL": "31","SF": "男"},{"XM": "王五2","NL": "30","SF": "女"},{"XM": "赵六2","NL": "23","SF": "女"}]}
{"index":{"_id":3}}
{"ajbh": "12345","ajmc": "立案案件","lasj": "2020/05/21 13:25:23","jsbax_sjjh2_xz_ryjbxx_cleaning": [{"XM": "张三3","NL": "30","SF": "男"},{"XM": "李四3","NL": "31","SF": "男"},{"XM": "王五3","NL": "30","SF": "女"},{"XM": "赵六3","NL": "23","SF": "男"}]}
GET test_index/_search
{
"aggs": {
"how_much_man": {
"sum": {
"script": {
"lang": "painless",
"source": """
int total = 0;
for(int i = 0;i<params._source.jsbax_sjjh2_xz_ryjbxx_cleaning.length;i++){
if(params._source.jsbax_sjjh2_xz_ryjbxx_cleaning[i].SF=="男"){
total++;
}
}
return total;
"""
}
}
}
}
}
GET test_index/_search
{
"aggs": {
"how_much_man": {
"sum": {
"script": {
"lang": "painless",
"source": """
int total = 0;
for(int i = 0;i<params['_source']['jsbax_sjjh2_xz_ryjbxx_cleaning'].length;i++){
if(params['_source']['jsbax_sjjh2_xz_ryjbxx_cleaning'][i]['SF']=='男'){
total++;
}
}
return total;
"""
}
}
}
}
}