ES[7.9]script脚本操作

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;
          """
        }
      }
    }
  }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,122评论 6 505
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,070评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,491评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,636评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,676评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,541评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,292评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,211评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,655评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,846评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,965评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,684评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,295评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,894评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,012评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,126评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,914评论 2 355

推荐阅读更多精彩内容