Given the fact that creating, deleting, and updating a single document in Elasticsearch is atomic,
it makes sense to store closely related entities within the same document.
考虑到在ES里面建立,删除和更新一个单一文本是原子性的,那么将相关实体保存在同一个文本里面是有意义的。
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" } ] }
Because all of the content is in the same document, there is no need to join blog posts and comments at query time, so searches perform well.
因为所有的内容都在同一文本里面,在查询的时候就没有必要拼接blog posts,因此检索性能会更好。
The problem is that the preceding document would match a query like this:
问题是,上面的文档会匹配这样的一个查询:
curl -XPGET 'localhost:9200/_search' -d ' { "query":{ "bool":{ "must":[ {"match":{"name":"Alice"}}, {"match":{"age":28}} ] } } }' 但是Alice is 31,不是28啊!
The reason for this cross-object matching, as discussed in Arrays of Inner Objects, is that our beautifully structured JSON document is flattened into a simple key-value format in the index that looks like this:
造成这种交叉对象匹配是因为结构性的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 ] }
The correlation between Alice and 31, or between John and 2014-09-01, has been irretrievably lost.
显然,像这种‘Alice’/‘31’,‘john’/’2014-09-01’间的关联性就不可避免的丢失了。
While fields of type object (see Multilevel Objects) are useful for storing a single object, they are useless, from a search point of view,
for storing an array of objects.
虽然object类型的字段对于保存一个单一的object很有用,但是从检索的角度来说,这对于保存一个object数组却是无用的。
This is the problem that nested objects are designed to solve。
nested object就是为了解决上述问题而设计出来的。
By mapping the commments field as type nested instead of type object, each nested object is indexed as a hidden separate document, something like this:
通过将comments字段映射为nested类型,而不是object类型,每一个nested object 将会作为一个隐藏的单独文本建立索引。如下:
{ ① "comments.name": [ john, smith ], "comments.comment": [ article, great ], "comments.age": [ 28 ], "comments.stars": [ 4 ], "comments.date": [ 2014-09-01 ] } { "comments.name": [ alice, white ], "comments.comment": [ like, more, please, this ], "comments.age": [ 31 ], "comments.stars": [ 5 ], "comments.date": [ 2014-10-22 ] } { "title": [ eggs, nest ], "body": [ making, money, work, your ], "tags": [ cash, shares ] } ①nested object
By indexing each nested object separately, the fields within the object maintain their relationships. We can run queries that will match only
if the match occurs within the same nested object.
通过分开给每个nested object建索引,object内部的字段间的关系就能保持。当执行查询时,只会匹配’match’同时出现在相同的nested object的结果.
Not only that, because of the way that nested objects are indexed, joining the nested documents to the root document at query time is fast—almost as fast as if they were a single document.
不仅如此,由于nested objects 建索引的方式,在查询的时候将根文本和nested文档拼接是很快的,就跟把他们当成一个单独的文本一样的快。
These extra nested documents are hidden; we can’t access them directly. To update, add, or remove a nested object, we have to reindex
the whole document. It’s important to note that, the result returned by a search request is not the nested object alone; it is the whole document.
这些额外的nested文本是隐藏的;我们不能直接接触。为了更新,增加或者移除一个nested对象,必须重新插入整个文本。要记住一点:查询请求返回的结果不仅仅包括nested对象,而是整个文本。
You may want to index inner objects both as nested fields and as flattened object fields, eg for highlighting. This can be achieved
by setting include_in_parent to true:
你可能想要检索内部object同时当作nested 字段和当作整平的object字段,比如为了强调。这可以通过将include_in_parent设置为true实现:
curl -XPUT 'localhost:9200/my_index' -d ' { "mappings":{ "blogpost":{ "properties":{ "comments":{ "type":"nested", "include_in_parent":true, "properties":{ "name": {"type":"string" }, "comment": { "type": "string" }, "age": { "type": "short" }, "stars": { "type": "short" }, "date": { "type": "date" } } } } } } }
The result of indexing our example document would be something like this:
查询结果类似这样:
{ "user.first" : "alice", "user.last" : "white" } { "user.first" : "john", "user.last" : "smith" } { "group" : "fans", "user.first" : [ "alice", "john" ], "user.last" : [ "smith", "white" ] }
Nested fields may contain other nested fields. The include_in_parent object refers to the direct parent of the field, while the include_in_root
parameter refers only to the topmost “root” object or document.
nested 字段可能会包含其他的nested 字段。include_in_parent object关联字段的直接上层,而include_in_root仅仅关联“根”obejct或文本
参考:
1.http://www.elastic.co/guide/en/elasticsearch/guide/master/nested-objects.html
2.http://www.elastic.co/guide/en/elasticsearch/reference/1.4/mapping-nested-type.html