Elasticsearch 中的嵌套字段(nested field)是一种特殊的数据类型,用于处理对象数组(object arrays)中的独立对象。与普通的对象数组不同,嵌套字段中的每个对象都是独立的文档,可以单独查询而不影响数组中的其他对象。
在默认情况下,Elasticsearch 会将对象数组扁平化处理。例如:
{
"user": [
{"first": "John", "last": "Smith"},
{"first": "Alice", "last": "White"}
]
}
会被存储为:
user.first: ["John", "Alice"]
user.last: ["Smith", "White"]
这会导致查询时无法关联同一对象中的字段。
在映射中定义嵌套字段:
PUT my_index
{
"mappings": {
"properties": {
"user": {
"type": "nested"
}
}
}
}
GET my_index/_search
{
"query": {
"nested": {
"path": "user",
"query": {
"bool": {
"must": [
{ "match": { "user.first": "Alice" }},
{ "match": { "user.last": "White" }}
]
}
}
}
}
}
GET my_index/_search
{
"aggs": {
"users": {
"nested": {
"path": "user"
},
"aggs": {
"names": {
"terms": { "field": "user.first" }
}
}
}
}
}
使用 inner_hits
获取匹配的嵌套对象:
GET my_index/_search
{
"query": {
"nested": {
"path": "user",
"query": { "match": { "user.first": "Alice" } },
"inner_hits": {}
}
}
}
原因:可能没有正确定义字段为嵌套类型,或者使用了普通的对象查询方式。
解决方案:
nested
nested
查询而非普通查询原因:嵌套查询需要额外的资源来处理嵌套文档。
解决方案:
ignore_unmapped
参数避免不必要的处理解决方案:
使用 inner_hits
并配置 docvalue_fields
或 stored_fields
来获取嵌套对象的原始位置信息。
PUT my_index/_doc/1
{
"user": [
{
"first": "John",
"last": "Smith",
"age": 30
},
{
"first": "Alice",
"last": "White",
"age": 25
}
]
}
GET my_index/_search
{
"query": {
"bool": {
"must": [
{
"nested": {
"path": "user",
"query": {
"bool": {
"must": [
{ "match": { "user.first": "Alice" }},
{ "range": { "user.age": { "gte": 20 }}}
]
}
},
"inner_hits": {
"size": 1,
"_source": ["user.first", "user.last"]
}
}
}
]
}
}
}
通过正确使用嵌套字段,可以有效地处理复杂的数据结构关系,实现更精确的数据查询和分析。