- 数据样例
索引名:nested
类型:doc1
{
"detail": [
{
"name": "美团",
"nid": 1200
}
],
"id": 1
}
- 添加
POST /nested/doc1/1/_update
{
"script": {
"lang": "painless",
"source": "ctx._source.detail.add(params.data);",
"params": {
"data": {
"name": "百度",
"nid": 1300
}
}
}
}
# 数据:
{
"_index": "nested",
"_type": "doc1",
"_id": "1",
"_score": 1.0,
"_source": {
"detail": [
{
"name": "美团",
"nid": 1200
},
{
"name": "百度",
"nid": 1300
}
],
"id": 1
}
}
- 修改
POST /nested/doc1/1/_update
{
"script": {
"lang": "painless",
"source": "for(e in ctx._source.detail){if (e.name == params.name) {e.nid = params.nid;}}",
"params": {
"name": "百度",
"nid": 1500
}
}
}
- 删除
POST /nested/doc1/1/_update
{
"script": {
"lang": "painless",
"source": "ctx._source.detail.removeIf(it -> it.nid ==params.nid);if(ctx._source.detail.length == 0){ctx.op='delete'}",
"params":{
"nid": 1200
}
}
}
# 删除后
{
"_index": "nested",
"_type": "doc1",
"_id": "1",
"_score": 1,
"_source": {
"detail": [
{
"name": "百度",
"nid": 1500
}
],
"id": 1
}
}
这个脚本先删除detail中nid=1200的元素,然后判断如果detail长度为0则删除这条数据。
如果指定的nid不存在,也会返回200,但数据的版本号+1
- 查询
GET /nested/doc1/_search
{
"query": {
"nested": {
"path": "detail",
"query": {
"term": {
"detail.nid": 1500
}
},
"inner_hits": {} # 返回嵌套查询命中的文档,可像普通查询那样添加from,size,_source等参数
}
}
}
- 使用脚本来获取每条数据中嵌套类型数组的长度
{
"query": {
"match_all": {}
},
"script_fields": {
"detail_count": { # 名称自定义
"script": {
"lang": "painless",
"source": "params['_source']['detail'].length"
}
}
},
"size": 100
}
params['_source']
和doc['xxx']
的区别:
doc
仅用于获取简单的(一个键对应一个值)、不分析的字段的值,像嵌套类型、文本类型等是不能用的。因此查询会缓存,速度快,但也意味着更多的内存消耗。params['_source']
每次使用都要加载和解析,所以速度慢。
推荐使用doc,不能用再使用params。
注意:
脚本中应避免使用硬编码,即使用类似下面的编写方式:
"source": "for(e in ctx._source.detail){if (e.name == '百度') {e.nid = 1500;}}",
这将导致脚本每次运行之前都要进行编译解析等工作,应当使用params
参数。如果脚本是固定的,可将脚本保存在es中,后续只需要传入脚本id和参数即可。