在 Elasticsearch (ES) 中,嵌套类型(nested
type)是一个特殊的复合类型,用于存储结构化的复杂对象,这些对象可以包含多个字段。使用嵌套类型的增、删、改、查操作与普通的字段操作相似,但由于嵌套类型具有层次结构,因此在查询时需要特别注意。
下面是如何在 Elasticsearch 中使用嵌套类型的增、删、改、查操作:
1. 创建索引并定义嵌套类型
首先,我们需要创建一个索引,并在映射中定义一个嵌套类型字段。假设我们有一个文档,其中包含一个嵌套的“address”字段,表示一个人可能有多个地址。
PUT /people
{
"mappings": {
"properties": {
"name": {
"type": "text"
},
"age": {
"type": "integer"
},
"addresses": {
"type": "nested", // 嵌套类型
"properties": {
"city": {
"type": "text"
},
"zipcode": {
"type": "keyword"
}
}
}
}
}
}
2. 增加文档(Indexing)
添加一个文档时,嵌套的字段可以作为数组来传入。
POST /people/_doc/1
{
"name": "John Doe",
"age": 30,
"addresses": [
{ "city": "New York", "zipcode": "10001" },
{ "city": "San Francisco", "zipcode": "94105" }
]
}
3. 查找文档(Search)
要查询嵌套字段中的数据,需要使用 nested
查询类型,并使用 nested_path
指定嵌套字段的路径。
查询所有地址是 “New York” 的人:
POST /people/_search
{
"query": {
"nested": {
"path": "addresses",
"query": {
"bool": {
"must": [
{ "match": { "addresses.city": "New York" } }
]
}
}
}
}
}
查询地址中包含 “zipcode” 为 “94105” 的人:
POST /people/_search
{
"query": {
"nested": {
"path": "addresses",
"query": {
"term": { "addresses.zipcode": "94105" }
}
}
}
}
4. 更新文档(Update)
更新嵌套类型的字段时,需要特别注意,因为 Elasticsearch 不支持直接修改嵌套数组中的单个元素。一般方法是使用 scripted_upsert
或先删除整个嵌套数组再重新添加。
示例:更新嵌套字段中的 “city”(例如,将地址 “New York” 的城市改为 “Los Angeles”):
POST /people/_update/1
{
"script": {
"source": """
for (int i = 0; i < ctx._source.addresses.size(); i++) {
if (ctx._source.addresses[i].city == 'New York') {
ctx._source.addresses[i].city = 'Los Angeles';
}
}
"""
}
}
5. 删除文档(Delete)
删除嵌套字段中的某个元素时,可以使用 script
来过滤删除,或完全删除文档后重新添加。
示例:删除 addresses
中城市为 “San Francisco” 的地址:
POST /people/_update/1
{
"script": {
"source": """
ctx._source.addresses.removeIf(addr -> addr.city == 'San Francisco');
"""
}
}
6. 删除文档(Delete by ID)
删除整个文档时,不需要关心嵌套字段,直接删除即可:
DELETE /people/_doc/1
7. 使用 Nested 聚合(Aggregation)
嵌套类型也可以用于聚合操作,以下是一个对嵌套字段进行聚合的例子。
示例:聚合所有城市的数量:
POST /people/_search
{
"aggs": {
"cities": {
"nested": {
"path": "addresses"
},
"aggs": {
"city_count": {
"terms": {
"field": "addresses.zipcode"
}
}
}
}
}
}
总结
在 Elasticsearch 中,嵌套类型允许你对结构化数据进行高效的存储和查询,但由于嵌套字段在查询时会被当作独立文档来处理,因此需要特别关注查询和更新的语法。通过 nested
查询和聚合,可以精确地定位和分析嵌套数据,而在更新和删除时,则通常需要通过脚本来操作嵌套字段。