Elasticsearch Scripting 教程

Elasticsearch Scripting 教程

Elasticsearch中最强大、有用的功能可能是其 Scripting 功能。通过脚本功能可以执行多种操作,如获取搜索请求的特定字段,修改、删除字段。本文学习如果通过脚本功能实现这些基本功能。

1. Elasticsearch Scripting介绍

Elasticsearch使用Painless或Java创建自定义表达式脚本。在5.x版本之后Painless作为默认版本。Painless更快、安全,比其他脚本语言更简单,语法与Java、groovy类似。

script作为请求主体的一个字段,其规范包括三个部分:

# the "script" field encompasses the main body of the JSON scripting request
"script": {

# scripting language name
"lang": "painless",

# source object (or document ID) as well as the operations performed by the script
"source": "ctx._source = params.someNum",

# the parameters or values for the script's operations
"params": { "someNum = 12345" }
}
  • lang

指定语言,从v5.x之后默认为Painless

  • source及ctx变量

使用ctx变量访问文档的source,即:ctx._source
查询时使用doc[‘field_name’].value访问字段值。

GET /courses/_search
{
  "query" : {
        "match_all": {}
  },
  "script_fields": {
    "db_enrolled": {
      "script": {
        "source": "doc['students_enrolled'].value * params.interval",
        "params": {"interval":2}
      }
    }
  }
}

上面示例给返回文档增加db_enrolled字段,其值为students_enrolled字段值两倍。

  • params

用于给脚本设定参数,脚本中引用参数:params.name ,name表示参数名称。

2. 创建索引

POST /testscript/_create/1
{
"personalDetails": {
     "name": "bob",
     "age": "13"
   },
   "marks": {
     "physics": 48,
     "maths": 45,
     "chemistry": 44
   },
   "remarks": [
     "hard working",
     "intelligent"
   ]
}

查询id为1的记录:

GET /testscript/_doc/1

返回内容:

{
  "_index" : "testscript",
  "_type" : "_doc",
  "_id" : "1",
  "_version" : 1,
  "_seq_no" : 1,
  "_primary_term" : 1,
  "found" : true,
  "_source" : {
    "personalDetails" : {
      "name" : "bob",
      "age" : "13"
    },
    "marks" : {
      "physics" : 48,
      "maths" : 45,
      "chemistry" : 44
    },
    "remarks" : [
      "hard working",
      "intelligent"
    ]
  }
}

3. 脚本更新文档

下面示例展示使用脚本更新文档的常用操作,主要包括:

  • 给索引增加新的字段
  • 更新已存在数组元素值
  • 删除数组元素
  • 删除字段

3.1. 给已存在字段增加新的属性

上面示例中包括三门课程成绩,现在我们增加英语的分数:

POST /testscript/_update/1
{
  "script": "ctx._source.marks.english=41"  
}

更新后记录已经改变,并且_version版本为2:

{
  "_index" : "testscript",
  "_type" : "_doc",
  "_id" : "1",
  "_version" : 2,
  "_seq_no" : 1,
  "_primary_term" : 1,
  "found" : true,
  "_source" : {
    "personalDetails" : {
      "name" : "bob",
      "age" : "13"
    },
    "marks" : {
      "physics" : 48,
      "maths" : 45,
      "chemistry" : 44,
      "english" : 41
    },
    "remarks" : [
      "hard working",
      "intelligent"
    ]
  }
}

版本数表明文档的改变次数。

3.2. 更新已存在字段属性值

接着我们更新physics的成绩为49:

POST /testscript/_update/1
{
  "script":{
    "source": "ctx._source.marks.physics=params.physics",
    "params": {"physics":49}
  }
}

验证结果:

{
  "_index" : "testscript",
  "_type" : "_doc",
  "_id" : "1",
  "_version" : 3,
  "_seq_no" : 2,
  "_primary_term" : 1,
  "found" : true,
  "_source" : {
    "personalDetails" : {
      "name" : "bob",
      "age" : "13"
    },
    "marks" : {
      "physics" : 49,
      "maths" : 45,
      "chemistry" : 44,
      "english" : 41
    },
    "remarks" : [
      "hard working",
      "intelligent"
    ]
  }
}

physics的值为49,版本为3,和预期一致。

3.3. 删除字段属性

删除物理成绩:

POST /testscript/_update/1
{
  "script":{
    "source": "ctx._source.marks.remove('physics')"
  }
}

验证结果:

{
  "_index" : "testscript",
  "_type" : "_doc",
  "_id" : "1",
  "_version" : 4,
  "_seq_no" : 3,
  "_primary_term" : 1,
  "found" : true,
  "_source" : {
    "personalDetails" : {
      "name" : "bob",
      "age" : "13"
    },
    "marks" : {
      "maths" : 45,
      "chemistry" : 44,
      "english" : 41
    },
    "remarks" : [
      "hard working",
      "intelligent"
    ]
  }
}

已经没有了物理成绩,版本为4。

3.4. 删除整个字段

删除marks整个字段:

POST /testscript/_update/1
{
  "script":{
    "source": "ctx._source.remove('marks')"
  }
}

验证结果是否一致:

{
  "_index" : "testscript",
  "_type" : "_doc",
  "_id" : "1",
  "_version" : 5,
  "_seq_no" : 4,
  "_primary_term" : 1,
  "found" : true,
  "_source" : {
    "personalDetails" : {
      "name" : "bob",
      "age" : "13"
    },
    "remarks" : [
      "hard working",
      "intelligent"
    ]
  }
}

3.5. 增加数组元素

增加一条评论:

POST /testscript/_update/1
{
  "script":{
    "source": "ctx._source.remarks.add('Love of learning')"
  }
}

验证结果:

{
  "_index" : "testscript",
  "_type" : "_doc",
  "_id" : "1",
  "_version" : 6,
  "_seq_no" : 5,
  "_primary_term" : 1,
  "found" : true,
  "_source" : {
    "personalDetails" : {
      "name" : "bob",
      "age" : "13"
    },
    "remarks" : [
      "hard working",
      "intelligent",
      "Love of learning"
    ]
  }
}

3.6. 删除数组元素

POST /testscript/_update/1
{
  "script":{
    "lang": "painless",
    "source": "ctx._source.remarks.remove(ctx._source.remarks.indexOf('Love of learning'))"
  }
}

4. 总结

本文学习了使用Elasticsearch中脚本模块简易修改文档字段值。

发布了395 篇原创文章 · 获赞 761 · 访问量 143万+

猜你喜欢

转载自blog.csdn.net/neweastsun/article/details/104287239