nested
-
场景描述:
在存储文档时,一个文档的属性包含多个对象时,需要使用nested类型进行定义。
-
场景例子:
一个文档的
Tags
属性,Tags
可以包含多个Tag
,每个Tag
都有TagKey
和TagValue
属性。"Tags": { "Tag": [ { "TagValue": "production", "TagKey": "env" }, { "TagValue": "xxxx", "TagKey": "group" } ] },
如果以
Tags
属性以普通的object
类型进行存储时,ES中没有内部对象的概念,会将内部对进行扁平化,扁平化后结如下:{ TagValue:[production,knorrcnyh5], TagKey:[env,group] }
扁平化处理过后,就无法再获得
env
与production
的关系了。在你查询env
等于production
的所有文档时,不符合条件的文档也会出现。 -
解决办法:
使用nested进行存储,mapping的定义如下:
project: properties: tags: type: nested properties: TagKey: type: keyword TagValue: type: keyword domain: type: text
nested进行增删改查:
- 查询 body:
{ query:{ nested:{ path: 'tags', query:{ bool:{ must:[ {match:{'tags.TagKey':'xxx'}}, {match:{'tags.TagValue':yyy}} ] } } } } }
- 增加 body:
bulk.push({ index: { _index: 'project', _type: 'asset', _id: instance.InstanceId, parent: parentId, }, }); bulk.push({ tags: getTags(instance), });
const getTags = ( instance ) => { const tags = []; for(let i = 0 ;i < instance.Tags.Tag.length; i++) { tags.push ( { TagKey: instance.Tags.Tag[i].TagKey, TagValue: instance.Tags.Tag[i].TagValue} ) } return tags; }
- 修改 body :
{ "script": { "source": "for(e in ctx._source.tags){if (e.tagKey == 'env') {e.tagValue = 'xxx';}}" } }
- 删除 body :
{ "script": { "lang": "painless", "source": "ctx._source.tags.removeIf(it -> it.tagKey == 'xxx');" } }