为了克服Arrays of Inner Objects 扁平化内部对象而丢失对象内部数据之间的关联信息的不足,Elasticsearch提供了Nested object。Nested object把每个内部对象做为一个独立的隐藏文件存储,从而保存了对象之间的独立性。对于nested object搜索,Elasticsearch也提供专门的搜索语法 -Querying a Nested Object。通过下面的例子,大家可以体会一下nested object和array of inner objects的区别:
(1) 索引一个包含两个内部对象的文档,默认情况下,Elasticsearch会使用array of inner object方式为他们创建mapping并进行索引。
PUT /testindex/object/1
{
"binaries": [
{
"extension": "pptx",
"description": "fancy presentation",
"size": 999
},
{
"extension": "pdf",
"description": "fancy presentation for all to read",
"size": 10
}
]
}
(2) 查看一下Elasticsearch为其创建的mapping。
{
"testindex": {
"mappings": {
"object": {
"properties": {
"binaries": {
"properties": {
"description": {
"type": "string"
},
"extension": {
"type": "string"
},
"size": {
"type": "long"
}
}
}
}
}
}
}
}
(3) 接下来我们搜索一下包括 extersion = pptx 同时 size<100 binary对象的文档。
GET /testindex/object/_search
{
"query": {
"filtered": {
"filter": {
"bool": {
"must": [
{
"term": {
"extension": "pptx"
}
},
{
"range": {
"size": {
"lte": 100
}
}
}
]
}
}
}
}
}
(4) 当前索引中只包含一个文档,我们可以清楚看到该文档并不包含extersion = pptx 同时 size<100 的binary对象。可是搜索结果仍然返回了一个结果,有些出人意料哦!这正是array of inner object确定,因为inner object的结构被扁平化存储,所以搜索是在横过了多个inner objects进行的。
{
"took": 1,
"timed_out": false,
"_shards": {
"total": 2,
"successful": 2,
"failed": 0
},
"hits": {
"total": 1,
"max_score": 1,
"hits": [
{
"_index": "testindex",
"_type": "object",
"_id": "1",
"_score": 1,
"_source": {
"binaries": [
{
"extension": "pptx",
"description": "fancy presentation",
"size": 999
},
{
"extension": "pdf",
"description": "fancy presentation for all to read",
"size": 10
}
]
}
}
]
}
}
(5)接下来我们来看看nestedobject是如何解决这个问题的,首先创建一个专门的nestedobject设计的mapping:
PUT /testindex/_mapping/nestedobject
{
"nestedobject": {
"properties": {
"binaries": {
"type": "nested",
"properties": {
"extension": {
"type": "string"
},
"description": {
"type": "string"
},
"size": {
"type": "long"
}
}
}
}
}
}
(6) 索引一个和之前的一样的文档:
PUT /testindex/nestedobject/2
{
"binaries": [
{
"extension": "pptx",
"description": "fancy presentation",
"size": 999
},
{
"extension": "pdf",
"description": "fancy presentation for all to read",
"size": 10
}
]
}
(7) 再用nested query来一把同样搜索条件的搜索吧。真神奇啊,没有任何结果返回,哈哈哈!这就是nested object.
GET /testindex/nestedobject/_search
{
"query": {
"filtered": {
"filter": {
"nested": {
"path": "binaries",
"filter": {
"bool": {
"must": [
{
"term": {
"extension": "pptx"
}
},
{
"range": {
"size": {
"lte": 100
}
}
}
]
}
}
}
}
}
}
}
鱼和熊掌可皆得吗? 当然。如果你既需要nested object同时也要扁平的object,在mapping中加入 include_in_parent即可,如下所示:
PUT /testindex/_mapping/nestedobject
{
"nestedobject": {
"properties": {
"binaries": {
"type": "nested",
"include_in_parent": true,
"properties": {
"extension": {
"type": "string"
},
"description": {
"type": "string"
},
"size": {
"type": "long"
}
}
}
}
}
}