nested
類型是一種特殊的對象
object
資料類型(specialised version of the object datatype ),允許對象數組彼此獨立地進行索引和查詢。
https://note.youdao.com/md/preview/preview.html?file=%2Fyws%2Fapi%2Fpersonal%2Ffile%2FWEB52c7421f2f8b35b47431f2ae68cb9c78%3Fmethod%3Ddownload%26read%3Dtrue#1-%E5%AF%B9%E8%B1%A1%E6%95%B0%E7%BB%84%E5%A6%82%E4%BD%95%E6%89%81%E5%B9%B3%E5%8C%96 1. 對象數組如何扁平化
内部對象
object
字段的數組不能像我們所期望的那樣工作。 Lucene沒有内部對象的概念,是以Elasticsearch将對象層次結構扁平化為一個字段名稱和值的簡單清單。 例如,以下檔案:
curl -XPUT 'localhost:9200/my_index/my_type/1?pretty' -H 'Content-Type: application/json' -d'
{
"group" : "fans",
"user" : [
{
"first" : "John",
"last" : "Smith"
},
{
"first" : "Alice",
"last" : "White"
}
]
}
'
說明
user
字段被動态的添加為
object
類型的字段。
在内部其轉換成一個看起來像下面這樣的文檔:
{
"group" : "fans",
"user.first" : [ "alice", "john" ],
"user.last" : [ "smith", "white" ]
}
user.first
和
user.last
字段被扁平化為多值字段,并且
alice
white
之間的關聯已經丢失。 本文檔将錯誤地比對
user.first
為
alice
user.last
smith
的查詢:
curl -XGET 'localhost:9200/my_index/_search?pretty' -H 'Content-Type: application/json' -d'
{
"query": {
"bool": {
"must": [
{ "match": { "user.first": "Alice" }},
{ "match": { "user.last": "Smith" }}
]
}
}
}
'
https://note.youdao.com/md/preview/preview.html?file=%2Fyws%2Fapi%2Fpersonal%2Ffile%2FWEB52c7421f2f8b35b47431f2ae68cb9c78%3Fmethod%3Ddownload%26read%3Dtrue#2-%E5%AF%B9%E5%AF%B9%E8%B1%A1%E6%95%B0%E7%BB%84%E4%BD%BF%E7%94%A8%E5%B5%8C%E5%A5%97%E5%AD%97%E6%AE%B5 2. 對對象數組使用嵌套字段
如果需要索引對象數組并維護數組中每個對象的獨立性,則應使用
nested
資料類型而不是
object
資料類型。 在内部,嵌套對象将數組中的每個對象作為單獨的隐藏文檔進行索引,這意味着每個嵌套對象都可以使用嵌套查詢
nested query
獨立于其他對象進行查詢:
curl -XPUT 'localhost:9200/my_index?pretty' -H 'Content-Type: application/json' -d'
{
"mappings": {
"my_type": {
"properties": {
"user": {
"type": "nested"
}
}
}
}
}
'
curl -XPUT 'localhost:9200/my_index/my_type/1?pretty' -H 'Content-Type: application/json' -d'
{
"group" : "fans",
"user" : [
{
"first" : "John",
"last" : "Smith"
},
{
"first" : "Alice",
"last" : "White"
}
]
}
'
user
字段映射為
nested
類型,而不是預設的
object
類型
curl -XGET 'localhost:9200/my_index/_search?pretty' -H 'Content-Type: application/json' -d'
{
"query": {
"nested": {
"path": "user",
"query": {
"bool": {
"must": [
{ "match": { "user.first": "Alice" }},
{ "match": { "user.last": "Smith" }}
]
}
}
}
}
}
'
此查詢得不到比對,是因為
Alice
Smith
不在同一個嵌套對象中。
curl -XGET 'localhost:9200/my_index/_search?pretty' -H 'Content-Type: application/json' -d'
{
"query": {
"nested": {
"path": "user",
"query": {
"bool": {
"must": [
{ "match": { "user.first": "Alice" }},
{ "match": { "user.last": "White" }}
]
}
},
"inner_hits": {
"highlight": {
"fields": {
"user.first": {}
}
}
}
}
}
}
'
此查詢得到比對,是因為
Alice
White
位于同一個嵌套對象中。
inner_hits
允許我們突出顯示比對的嵌套文檔。
輸出
{
"took": 6,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"failed": 0
},
"hits": {
"total": 1,
"max_score": 1.987628,
"hits": [
{
"_index": "my_index",
"_type": "my_type",
"_id": "1",
"_score": 1.987628,
"_source": {
"group": "fans",
"user": [
{
"first": "John",
"last": "Smith"
},
{
"first": "Alice",
"last": "White"
}
]
},
"inner_hits": {
"user": {
"hits": {
"total": 1,
"max_score": 1.987628,
"hits": [
{
"_index": "my_index",
"_type": "my_type",
"_id": "1",
"_nested": {
"field": "user",
"offset": 1
},
"_score": 1.987628,
"_source": {
"first": "Alice",
"last": "White"
},
"highlight": {
"user.first": [
"<em>Alice</em>"
]
}
}
]
}
}
}
}
]
}
}
嵌套文檔可以:
- 使用 nested 查詢進行查詢
- reverse_nested 聚合進行分析
- 排序進行排序
- nested inner hits 進行檢索與突出顯示
https://note.youdao.com/md/preview/preview.html?file=%2Fyws%2Fapi%2Fpersonal%2Ffile%2FWEB52c7421f2f8b35b47431f2ae68cb9c78%3Fmethod%3Ddownload%26read%3Dtrue#3-%E5%B5%8C%E5%A5%97%E5%AD%97%E6%AE%B5%E5%8F%82%E6%95%B0 3. 嵌套字段參數
嵌套字段接受以下參數:
參數 | 描述 |
---|---|
dynamic | 是否将新屬性動态添加到現有的嵌套對象。共有 (預設), 三種參數。 |
include_in_all | Sets the default include_in_all value for all the properties within the nested object. Nested documents do not have their own _all field. Instead, values are added to the _all field of the main “root” document. |
properties | 嵌套對象中的字段,可以是任何資料類型,包括嵌套。新的屬性可能會添加到現有的嵌套對象。 |
備注
類型映射(
type mapping
)、對象字段和嵌套字段包含的子字段,稱之為屬性
properties
。這些屬性可以為任意資料類型,包括
object
和
nested
。屬性可以通過以下方式加入:
- 當在建立索引時顯式定義他們。
- 當使用
添加或更新映射類型時顯式地定義他們。PUT mapping API
- 當索引包含新字段的文檔時動态的加入。
重要
由于嵌套文檔作為單獨的文檔進行索引,是以隻能在
nested
查詢,
nested
/
reverse_nested
聚合或者
的範圍内進行通路。
For instance, if a string field within a nested document has index_options set to offsets to allow use of the postings highlighter, these offsets will not be available during the main highlighting phase. Instead, highlighting needs to be performed via nested inner hits.
https://note.youdao.com/md/preview/preview.html?file=%2Fyws%2Fapi%2Fpersonal%2Ffile%2FWEB52c7421f2f8b35b47431f2ae68cb9c78%3Fmethod%3Ddownload%26read%3Dtrue#4-%E9%99%90%E5%88%B6%E5%B5%8C%E5%A5%97%E5%AD%97%E6%AE%B5%E7%9A%84%E4%B8%AA%E6%95%B0 4. 限制嵌套字段的個數
索引一個擁有100個嵌套字段的文檔,相當于索引了101個文檔,因為每一個嵌套文檔都被索引為一個獨立的文檔.為了防止不明确的映射,每個索引可以定義的嵌套字段的數量已被限制為50個。 具體請參閱
Settings to prevent mappings explosion原文:
https://www.elastic.co/guide/en/elasticsearch/reference/current/nested.html#nested-params