Nested 数据类型
nested 类型是特殊的object类型,它可以使对象数组已相对独立的查询方式进行索引。
对象数组是如何展平的
内部对象数组的字段并不是期望的那样工作。Lucene 并没有内部对象的概念,所以 elasticsearch 展平了对象的层级,变成了字段名称和值的简单列表。如:
PUT my_index/_doc/1{"group" : "fans","user" : [{"first" : "John","last" : "Smith"},{"first" : "Alice","last" : "White"}]}
自动添加了
object类型的user字段。
该文档将会在内部转换为如下的文档:
{"group" : "fans","user.first" : [ "alice", "john" ],"user.last" : [ "smith", "white" ]}
其中user.first和user.last字段将会被展平为多值字段,而alice 与white的关联关系丢失了。当查询alice AND smith时会错误的匹配到该文档。
GET my_index/_search{"query": {"bool": {"must": [{ "match": { "user.first": "Alice" }},{ "match": { "user.last": "Smith" }}]}}}
使用 nested类型的对象数组
如果希望索引对象数组,并保持数组中每个对象的独立性,应该使用nested类型,而不是object类型。在内部,嵌套类型将数组中的对象索引为独立的隐藏文档,意味着使用nested 查询,可以独立的查询每个嵌套对象。
PUT my_index{"mappings": {"_doc": {"properties": {"user": {"type": "nested"}}}}}PUT my_index/_doc/1{"group" : "fans","user" : [{"first" : "John","last" : "Smith"},{"first" : "Alice","last" : "White"}]}GET my_index/_search{"query": {"nested": {"path": "user","query": {"bool": {"must": [{ "match": { "user.first": "Alice" }},{ "match": { "user.last": "Smith" }}]}}}}}GET my_index/_search{"query": {"nested": {"path": "user","query": {"bool": {"must": [{ "match": { "user.first": "Alice" }},{ "match": { "user.last": "White" }}]}},"inner_hits": {"highlight": {"fields": {"user.first": {}}}}}}}
user字段主动映射为nested类型;第一个查询不会命中,
AliceandSmith并不在同一个嵌套文档中;第二个查询成功命中;
inner_hits可以高亮匹配到的嵌套文档;
嵌套文档可以:
- 使用 nested 查询;
- 使用
nestedandreverse_nestedaggregations 分析; - 使用 nested sorting;
- 获取并高亮,通过 nested inner hits;
nested 类型的参数
dynamic:新属性是否可以动态的添加到 nested 类型的对象中,true(默认),false,strict;
properties:嵌套对象中的字段,可以是任意数据类型,包括 nested。可以将新属性添加到现有的嵌套类型对象中。
注:
因为嵌套类型的文档被索引在独立的文档中,它们仅可以通过
nested查询、nested/reverse_nested聚合,或者 nested inner hits 访问。例如,嵌套文档中的一个字符串字段设置了
index_options为offsetto allow use of the postings,在标记阶段,这些 offsets 在主要标记阶段不会生效。相反,高亮操作需要通过 nested inner hits 执行。(不懂这句)
限制 nested 类型字段的数量
索引一个 100 个嵌套字段的文档,实际上索引了 101 个文档(一个嵌套字段会产生一个隐藏文档,并不是一个嵌套数组的对象产生一个隐藏文档???),因为每一个嵌套文档都被索引一个单独的文档。为了防止定义不明确的映射,每个索引可以定义的嵌套字段数量限制在 50 个。
