Elasticsearch 中的脚本编程能力

发表于2020-07-27,长度3134, 295个单词, 8分钟读完
Flag Counter

elasticsearch 和 关系型数据库在使用上类似,都是建表(创建mapping)、插入、查询、删除、更新、表结构变更(mapping 变更)等等。基于基本的增删改查用的最多也比较简单,而mapping结构的处理要相对复杂一点。这里简单介绍一下如何使用es 的脚本能力轻松变更mapping 结构。

为成熟的中间件提供编程能力正成为中间件热衷的能力,比如redis也支持lua编程(《在Redis中使用Lua脚本》)

〇 es 脚本能力简介

es脚本能实现一些rest api无法搞定的事情,从这一个角度看,它存在的意义重大:因为它有一个无法被代替的能力。如果我们自己身上也有别人无法代替的特质,那么我们就是这个世界重要的组成部分😁。

可惜我们没有,所以地球离了我们还是在转😭

从1.4版本开始,es推荐使用groovy做为默认脚本。实际上,es 支持好几种脚本引擎,除了groovy,还有大家熟悉的js/python,还有Expression/Mustache/mvel。大家可以自行了解一下。

通过es脚本,我们可以更新es记录的字段、增加字段、删除字段,而后面这两个能力,不使用脚本的话实现起来很费劲。

壹 更新字段

我们先来创建一个索引:

curl -XPUT 'localhost:9200/testindex/_doc/1' -H 'content-Type:application/json' -d '{
   "marks": {
     "physics": 48,
     "maths": 45,
     "chemistry": 44
   },
   "remarks": [
     "hard working",
     "intelligent"
   ]
 }'

这条记录包含两个nested字段,并且没有指明字段类型,所以es会自动映射:

"marks": {
    "properties": {
        "chemistry": {
            "type": "long"
        },
        "maths": {
            "type": "long"
        },
        "physics": {
            "type": "long"
        }
    }
},
"remarks": {
    "type": "text",
    "fields": {
        "keyword": {
            "ignore_above": 256,
            "type": "keyword"
        }
    }
}

接下来通过脚本更新物理课的分数为59(差点及格):

希望你已经知道不使用脚本是如何更新记录的

curl -XPOST 'localhost:9200/testindex/_doc/1/_update' -H 'Content-Type: application/json' -d '{
    "script" : "ctx._source.marks.physics = 59"
}'

我们看一下请求格式:json参数有一个字段叫script,里面通过ctx的_source拿到记录,然后通过点号指明marks字段的physics字段的值。

贰 增加字段

不使用脚本如何增加字段?这个已经不是一个常规问题,虽然做法简单,但是了解的人不多:

 curl -XPUT 'http://127.0.0.1:9200/testindex/_mapping/_doc?pretty' -H 'Content-Type: application/json' -d'
{
  "properties": {
    "long_followerCount": {
      "type": "long"
    }
  }
}'

通过index/_mapping/type的PUT请求直接传入一个字段就可以新增。

那通过脚本怎么实现呢?

curl -XPOST 'localhost:9200/testindex/_doc/1/_update' -H 'Content-Type: application/json' -d '{
    "script" : "ctx._source.marks.english = 41"
}'

直接写入一个值就完成了新增。当然是动态结构了。

现在整个mapping是:

"properties": {
    "marks": {
        "properties": {
            "chemistry": {
                "type": "long"
            },
            "maths": {
                "type": "long"
            },
            "physics": {
                "type": "long"
            },
            "english": {
                "type": "long"
            }
        }
    },
    "long_followerCount": {
        "type": "long"
    },
    "remarks": {
        "type": "text",
        "fields": {
            "keyword": {
                "ignore_above": 256,
                "type": "keyword"
            }
        }
    }
}

叁 删除字段

通过脚本删除字段也很简单:

curl -XPOST 'localhost:9200/testindex/_doc/1/_update' -H 'Content-Type: application/json' -d '{
  "script": "ctx._source.marks.remove(\"physics\")"
}'

curl -XPOST 'localhost:9200/testindex/_doc/1/_update' -H 'Content-Type: application/json' -d '{
  "script": "ctx._source.remove(\"marks\")"
}'

上面分别通过记录删除了它的physics和marks字段。是不是比以前的方法简单多了?

肆 自定义查询

通过脚本可以进行自定义的字段及格式查询:

curl -XGET 'localhost:9200/testindex/_search' -H 'Content-Type: application/json' -d '{
  "script_fields": {
    "my_field": {
      "script": {
        "lang":   "expression",
        "source": "doc['long_followerCount'] * multiplier",
        "params": {
          "multiplier": 2
        }
      }
    }
  }
}'

这里查询的是long_followerCount这个字段的2倍。

Written on July 27, 2020
分类: dev, 标签: elasticsearch
如果你喜欢,请赞赏! davelet