文章目錄
- 一、Object 類型:默認的嵌套對象處理方式
- 核心原理
- 典型場景
- 關鍵限制
- 二、Nested 類型:解決嵌套數組的關聯查詢
- 核心原理
- 典型場景
- 使用示例
- 注意事項
- 三、Join 類型:跨文檔的父子關聯
- 核心原理
- 典型場景
- 使用示例
- 注意事項
- 四、Flattened 類型:動態嵌套對象的輕量化處理
- 核心原理
- 典型場景
- 使用示例
- 注意事項
- 五、類型對比與選擇建議
Elasticsearch 作為面向文檔的搜索引擎,對嵌套數據的處理有多種方式,不同類型適用于不同的業務場景。
一、Object 類型:默認的嵌套對象處理方式
核心原理
Elasticsearch 中,JSON 文檔的嵌套對象(如 {"user": {"name": "張三", "age": 25}}
)會被默認映射為 Object 類型
。其底層通過 字段扁平化 實現索引:將嵌套對象的字段展開為 父字段.子字段
的形式(如 user.name
、user.age
),存儲為獨立的字段。
典型場景
適用于 簡單嵌套對象,且不需要對嵌套對象內部字段進行 關聯查詢 的場景。例如:
{"article": {"title": "ES 數據類型指南","author": { "name": "李四", "email": "lisi@example.com" }}
}
此時 author
是一個簡單對象,若只需查詢 author.name
或 author.email
的獨立值(不關心是否屬于同一作者),Object 類型足夠。
關鍵限制
當嵌套對象是 數組 時(如一個用戶有多個地址),Object 類型會 丟失對象內部字段的關聯。例如:
{"user": "張三","addresses": [{"city": "北京", "zip": "100000"},{"city": "上海", "zip": "200000"}]
}
Elasticsearch 會將 addresses.city
存儲為 ["北京", "上海"]
,addresses.zip
存儲為 ["100000", "200000"]
。若執行查詢 city=北京 AND zip=200000
,會錯誤匹配到這條文檔(因為字段被扁平化,不關心“北京”和“200000”是否屬于同一個地址對象)。
二、Nested 類型:解決嵌套數組的關聯查詢
核心原理
Nested 類型是 Object 類型的擴展,專門用于處理 嵌套對象數組。它將數組中的每個對象 獨立索引為一個“子文檔”,保留對象內部字段的關聯關系。查詢時需使用 nested 查詢
,確保只匹配同一嵌套對象內的字段。
典型場景
適用于 一對多關聯 且需要對嵌套對象內部字段進行 組合查詢 的場景。例如:
- 訂單的多個商品(需查詢“購買了蘋果手機且數量>2的訂單”);
- 用戶的多個地址(需查詢“城市為北京且郵編為100000的地址”)。
使用示例
映射定義:
PUT /my_index
{"mappings": {"properties": {"user": {"type": "nested", // 指定為 nested 類型"properties": {"name": {"type": "keyword"},"address": {"type": "nested", // 支持多層嵌套"properties": {"city": {"type": "keyword"},"zip": {"type": "keyword"}}}}}}}
}
查詢示例(匹配同一地址內的城市和郵編):
GET /my_index/_search
{"query": {"nested": {"path": "user.address", // 指定嵌套路徑"query": {"bool": {"must": [{"term": {"user.address.city": "北京"}},{"term": {"user.address.zip": "100000"}}]}}}}
}
注意事項
- 性能與存儲:每個嵌套對象獨立索引,會增加索引體積(約為普通 Object 類型的 1.5~3 倍);
- 嵌套層級:支持多層嵌套(如
user.address.street
),但深度建議不超過 5 層(過深會影響查詢性能); - 更新限制:修改嵌套對象的任意字段需重新索引整個父文檔(類似關系型數據庫的級聯更新)。
三、Join 類型:跨文檔的父子關聯
核心原理
Join 類型允許在 同一索引 中建立父子文檔關系(如父文檔是“用戶”,子文檔是“用戶的訂單”)。通過 _parent
字段關聯父子文檔,父文檔和子文檔需存儲在 同一分片 上(通過父文檔的 _id
哈希到分片)。
典型場景
適用于 跨文檔的一對多關聯,且父子文檔需要 獨立更新 的場景。例如:
- 論壇的“板塊(父)- 帖子(子)”;
- 企業的“部門(父)- 員工(子)”。
使用示例
映射定義:
PUT /my_index
{"mappings": {"properties": {"join_field": { "type": "join","relations": {"department": "employee" // 父類型: "department",子類型: "employee"}}}}
}
創建父文檔(部門):
PUT /my_index/_doc/1
{"name": "技術部","join_field": { "name": "department" } // 標記為父類型
}
創建子文檔(員工):
PUT /my_index/_doc/2?routing=1 // 必須與父文檔同分片(routing=父文檔ID)
{"name": "張三","join_field": { "name": "employee", "parent": "1" // 關聯父文檔ID}
}
查詢示例(查詢技術部的所有員工):
GET /my_index/_search
{"query": {"has_parent": {"parent_type": "department","query": { "term": { "name": "技術部" } }}}
}
注意事項
- 性能瓶頸:父子查詢需要跨文檔關聯(類似關系型數據庫的
JOIN
),性能低于 Nested 類型(Nested 是單文檔內的關聯); - 分片限制:父文檔和子文檔必須同分片,若父文檔分布不均可能導致分片數據傾斜;
- 適用場景:僅當父子文檔需要 獨立更新(如父文檔修改不影響子文檔)時使用,否則優先選擇 Nested 類型。
四、Flattened 類型:動態嵌套對象的輕量化處理
核心原理
Flattened 類型用于將 復雜的嵌套 JSON 對象(如動態結構的元數據)展平為單個字段。所有嵌套的鍵會被合并為 點分隔的字符串
(如 {"a": {"b": "c"}}
會被展平為 a.b: c
),并索引為 keyword
類型(支持精確匹配)。
典型場景
適用于 動態或未知結構的嵌套對象,例如:
- 日志中的
tags
字段(可能包含任意層級的鍵值對); - 商品的擴展屬性(如不同品類的額外信息)。
使用示例
映射定義:
PUT /my_index
{"mappings": {"properties": {"metadata": {"type": "flattened" // 指定為 flattened 類型}}}
}
文檔示例:
PUT /my_index/_doc/1
{"metadata": {"user": {"name": "張三","age": 25},"device": "iPhone 15"}
}
此時 metadata
會被展平為 metadata.user.name: "張三"
、metadata.user.age: "25"
、metadata.device: "iPhone 15"
等字段。
查詢示例(精確匹配展平后的路徑):
GET /my_index/_search
{"query": {"term": { "metadata.user.name": "張三" } // 直接使用展平后的字段名}
}
注意事項
- 字段限制:展平后的字段數量默認最多 1000 個(可通過
max_flattened_fields
參數調整); - 查詢能力:僅支持精確匹配(
term
)或前綴匹配(prefix
),無法進行范圍查詢(如age>20
); - 適用場景:優先用于 不需要復雜查詢 的動態嵌套對象(如日志元數據),避免因動態映射導致字段爆炸。
五、類型對比與選擇建議
類型 | 核心特點 | 適用場景 | 性能與限制 |
---|---|---|---|
Object | 扁平化存儲,丟失嵌套對象關聯 | 簡單嵌套對象,無需關聯查詢 | 輕量,無法處理嵌套數組的關聯查詢 |
Nested | 獨立索引嵌套對象,保留關聯 | 一對多嵌套數組,需關聯查詢 | 索引體積大,更新成本高 |
Join | 跨文檔父子關聯 | 父子需獨立更新,跨文檔查詢 | 查詢性能差,分片限制嚴格 |
Flattened | 展平動態嵌套對象,簡化索引 | 動態/未知結構的嵌套對象,輕查詢 | 僅支持精確匹配,字段數量受限 |
選擇建議:
- 優先使用
Nested 類型
處理嵌套數組的關聯查詢(如訂單-商品); - 僅當父子需獨立更新時使用
Join 類型
(如部門-員工); - 動態或未知結構的嵌套對象用
Flattened 類型
(如日志元數據); - 簡單嵌套對象且無需關聯查詢時,使用默認的
Object 類型
。