es嵌套字段必须显式声明为nested类型,否则inner_hits无法返回匹配子项、nested查询静默失效;正确写法是mapping中指定"type":"nested",查询时用path+query包裹、inner_hits需显式设size,聚合须嵌套aggs。

ES嵌套字段必须显式声明为 nested 类型
直接在 mapping 里把字段设成 object,哪怕结构再深,Elasticsearch 也当普通对象处理——inner_hits 拿不到匹配子项,nested 查询会静默失效或返回空。你查 comments.author.name 却得不到结果,大概率是 mapping 没配对。
正确做法是在创建索引时明确指定:
{
"mappings": {
"properties": {
"comments": {
"type": "nested",
"properties": {
"author": {
"type": "object",
"properties": {
"name": { "type": "keyword" },
"email": { "type": "keyword" }
}
}
}
}
}
}
}
已建索引要改类型?只能 reindex,PUT _mapping 不支持改 nested 层级。
nested 查询必须用 path + query 两层包裹
写 {"term": {"comments.author.name": "foo"}} 这种扁平写法,ES 会当成普通字段查,根本不会进嵌套逻辑。所有嵌套字段访问必须走 nested 查询语法:
-
path值必须是完整嵌套路径(如comments),不能写comments.author或comments.author.name -
query内部才是真正的条件,且字段名只写相对路径(如author.name) - 想取匹配的子文档?加
inner_hits,但注意它默认只返回前 3 条,要改数量得显式设"size": 10
示例:
{
"query": {
"nested": {
"path": "comments",
"query": {
"term": { "comments.author.name": "foo" }
},
"inner_hits": { "size": 5 }
}
}
}
聚合(aggs)里访问嵌套字段要先 nested 再 terms
直接 "aggs": {"by_name": {"terms": {"field": "comments.author.name.keyword"}}} 会聚合失败或结果为空——ES 聚合不自动穿透 nested 结构。
必须用 nested 聚合做“进入”动作,再在内部做具体聚合:
- 外层
nested的path和查询一致(如comments) - 内层
terms字段写相对路径(如author.name.keyword),前面不带comments. - 如果还要按多层分组(比如先按
author.id,再按status),得套两层nested,但注意性能损耗会明显上升
示例:
{
"aggs": {
"comments_agg": {
"nested": {
"path": "comments"
},
"aggs": {
"by_author": {
"terms": { "field": "comments.author.name.keyword" }
}
}
}
}
}
Laravel 客户端拼接嵌套查询时,别用数组键名自动展开
用 elasticsearch/elasticsearch 客户端时,常见错误是把查询体写成 PHP 数组后直接传入,指望框架自动转义路径。比如:
$params['body']['query']['nested']['path'] = 'comments'; $params['body']['query']['nested']['query']['term']['comments.author.name'] = 'foo';
这看似没问题,但一旦 comments.author.name 中含点号,PHP 数组无法表达层级,某些中间封装层(如 Scout 扩展)会把它当字符串扁平处理,导致 DSL 错位。
更稳妥的方式是:手写完整 JSON 字符串,或用 json_decode(..., true) 构建嵌套结构,确保 query 下的字段路径完全由你自己控制。尤其注意 inner_hits 的配置位置——它必须和 query 同级,不是 query 的子键。
真正容易被忽略的是:nested 字段的 score_mode 默认是 avg,如果你希望主文档得分由任意一个匹配子项决定,得显式设 "score_mode": "max",否则排序可能不符合预期。











