ElasticSearch的Nested(巢狀)資料型別
[[nested]]
=== Nested(巢狀)資料型別
nested
型別是一種特殊的 [object,object
] 型別.
這種型別允許對 object 陣列內的元素進行單獨查詢.
object 陣列是怎麼展開(flatten)的
[object,object
] 陣列的功能可能跟你想象中的不太一樣.
Lucene 沒有內部 object 的概念, 所以 Elasticsearch 內部會把 object 解析成簡單的欄位名與值的資訊,
以下面這個文件為例:
[source,js]
PUT my_index/_doc/1
{
"group" : "fans",
"user" : [ <1>
{
"first" : "John",
"last" : "Smith"
},
{
"first" : "Alice",
"last" : "White"
}
]
}
<1> user
被欄位配置為 object
欄位.
內部會把文件轉化為類似與下面這種形式:
[source,js]
{
"group" : "fans",
"user.first" : [ "alice", "john" ],
"user.last" : [ "smith" , "white" ]
}
user.first
和 user.last
被展開成多值欄位,
而且 alice
與 white
之間的關係被丟棄了.
這個文件可能會錯誤地匹配 alice AND smith
.
[source,js]
GET my_index/_search
{
"query": {
"bool": {
"must": [
{ "match": { "user.first": "Alice" }},
{ "match": { "user.last": "Smith" }}
]
}
}
}
將 object 陣列欄位配置為 nested
如果你需要保留 object 陣列中每個物件的內部關係, 則需要使用 nested
型別, 而不是 [object,object
] 型別.
Elasticsearch 內部會把陣列中的每個元素當成一個隱藏文件, 所以可以用 [query-dsl-nested-query,nested
query]
單獨對每個元素進行查詢:
[source,js]
PUT my_index
{
"mappings": {
"_doc": {
"properties": {
"user": {
"type": "nested" <1>
}
}
}
}
}
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" }} <2>
]
}
}
}
}
}
GET my_index/_search
{
"query": {
"nested": {
"path": "user",
"query": {
"bool": {
"must": [
{ "match": { "user.first": "Alice" }},
{ "match": { "user.last": "White" }} <3>
]
}
},
"inner_hits": { <4>
"highlight": {
"fields": {
"user.first": {}
}
}
}
}
}
}
<1> user
被配置為 nested
而不是 object
.
<2> 無法查詢到資料, 因為 Alice
和 Smith
不在同一個 nested object.
<3> 可以查詢到資料, 因為 Alice
和 White
在相同一個 nested object.
<4> inner_hits
允許高亮匹配到的 nested 文件.
Nested 文件可以:
- 用 [query-dsl-nested-query,
nested
] 進行查詢. - 用 [search-aggregations-bucket-nested-aggregation,
nested
]
和 [search-aggregations-bucket-reverse-nested-aggregation,reverse_nested
]
進行聚合分析. - 用 [nested-sorting,nested sorting] 進行排序.
- 用 [nested-inner-hits,nested inner hits] 獲取和高亮.
[[nested-params]]
nested
的引數
nested
欄位支援以下引數:
[horizontal]
[dynamic,dynamic
]:
是否把新的 `屬性` 自動新增到已有的巢狀物件. 接收 `true` (預設), `false` 和 `strict`.
[properties,properties
]:
巢狀物件包含的欄位, 可以是任意的
[mapping-types,資料型別], 包括 `nested`, 新的 `屬性` 可能會被新增到已有的巢狀物件.
[IMPORTANT]
因為 nested 文件被索引為單獨的文件, 所以只能使用 nested
查詢, nested
/reverse_nested
聚合, 或者用 [nested-inner-hits,nested inner hits].
例如, 對一個 nested 文件中的 string 欄位用 [index-options,index_options
] 對 offsets
進行設定, 是沒有用的.
需要用 [nested-inner-hits,nested inner hits].
=============================================
限制 nested
欄位的數量
索引一個有 100個 nested
欄位的文件, 實際上需要索引 101 個文件, 因為每個巢狀物件會被當成一個隱藏文件.
為了防止某些錯誤配置的 mapping, nested
欄位的數量可以限制為每個 index 最多 50 個. 詳情參考 [mapping-limit-settings].