Nested Objects 嵌套对象简介

来源:互联网 发布:c语言做网页 编辑:程序博客网 时间:2024/06/10 16:10


在Elasticsearch中进行创建、删除和更新一个单个的文档的时候它是原子性的操作,所以在同一文档中存储紧密相关的实体是有道理的(百度翻译)。比如将一篇博客和它所有的评论存储在一起,可以通过一个comments数组实现:

PUT /my_index/blogpost/1{  "title": "Nest eggs",  "body":  "Making your money work...",  "tags":  [ "cash", "shares" ],  "comments": [     {      "name":    "John Smith",      "comment": "Great article",      "age":     28,      "stars":   4,      "date":    "2014-09-01"    },    {      "name":    "Alice White",      "comment": "More like this please",      "age":     31,      "stars":   5,      "date":    "2014-10-22"    }  ]}

如果我们使用动态映射,commets字段将会被自动创建成一个object对象类型的字段

由于所有的内容都在一个文档中,所以在查询的时候不需要对bolg posts和commets进行联合查询,搜索性能也会更好

但是有时候会出现如下的一个问题:

GET /_search{  "query": {    "bool": {      "must": [        { "match": { "comments.name": "Alice" }},        { "match": { "comments.age":  28      }}       ]    }  }}

我们想搜索评论里name中含有Alice、 age为28的评论者信息,但是搜索结果如下


可以看到JohnSimth和AliceWhite都被搜索了出来,因为John的age与搜索条件中的age为28匹配,Alice与搜索条件中name含有Alice匹配


造成这个的原因是在索引中结构化的JSON文档被扁平化成一个如下的键值对形式:

{  "title":            [ eggs, nest ],  "body":             [ making, money, work, your ],  "tags":             [ cash, shares ],  "comments.name":    [ alice, john, smith, white ],  "comments.comment": [ article, great, like, more, please, this ],  "comments.age":     [ 28, 31 ],  "comments.stars":   [ 4, 5 ],  "comments.date":    [ 2014-09-01, 2014-10-22 ]}
Alice和31、John和2014-09-01之间的相关性被丢失了,对象类型的字段在存储一个单个的对象时是非常有用的,但是对存储一系列对象数组时就变得没用了。

这个问题可以使用nested对象来解决。将comments映射为一个nested对象类型而不是一个普通的object类型,每个nested对象被索引为隐藏的单独文档,如下所示:

{ //1  "comments.name":    [ john, smith ],  "comments.comment": [ article, great ],  "comments.age":     [ 28 ],  "comments.stars":   [ 4 ],  "comments.date":    [ 2014-09-01 ]}{ //2  "comments.name":    [ alice, white ],  "comments.comment": [ like, more, please, this ],  "comments.age":     [ 31 ],  "comments.stars":   [ 5 ],  "comments.date":    [ 2014-10-22 ]}{//3   "title":            [ eggs, nest ],  "body":             [ making, money, work, your ],  "tags":             [ cash, shares ]}

1是第一个nested对象

2是第二个nested对象

3是根(父)文档


总结:

通过分别对每个嵌套对象进行索引,对象中字段之间的关系可以被维持。我们可以执行一个查询,只有match发生在同一个nested对象时它才会匹配。

不仅如此,由于nested对象被索引的方式,在查询的时候联合nested文档到根文档的速度是非常快的,几乎与查询单个的的文档一样快。

另外,nested文档是隐藏的,我们不能直接访问它。当更新、添加或者删除一个nested对象,必须重新索引整个文档,需要注意的是,发送一个搜索请求时返回的是整个文档而不是只返回nested对象。


翻译自官方文档:https://www.elastic.co/guide/en/elasticsearch/guide/current/nested-objects.html

0 0
原创粉丝点击