Elasticsearch 6.8:查询嵌套字段求和与非嵌套字段不等的文档
解决Elasticsearch 6.8中嵌套字段求和与根字段对比及更新问题
一、查询:找出Accounts.FollowersCount总和与TotalSubscribers不相等的文档
你原来的查询脚本错误在于直接遍历doc['Accounts'],在Painless中,嵌套字段的数值类型会被自动处理为数组存储在doc['Accounts.FollowersCount']中,不需要手动循环,直接调用sum()方法就能快速得到总和。同时要注意保持类型匹配(两者都是long类型,避免int溢出风险)。
正确的查询脚本如下:
{ "_source": ["TotalSubscribers", "Accounts.FollowersCount"], "query": { "bool": { "filter": { "script": { "script": { "source": "doc['Accounts.FollowersCount'].sum() != doc['TotalSubscribers'].value", "lang": "painless" } } } } } }
如果需要兼容Accounts数组为空的场景(此时sum()会返回0),可以补充空数组判断逻辑:
"source": "def followersSum = doc['Accounts.FollowersCount'].size() > 0 ? doc['Accounts.FollowersCount'].sum() : 0; return followersSum != doc['TotalSubscribers'].value"
二、更新:将Accounts.FollowersCount的总和赋值给TotalSubscribers
你的更新脚本报错核心原因是:部分Accounts元素可能缺失FollowersCount字段,导致访问空属性时抛出空指针异常。需要在遍历过程中添加空值判断,确保不会触发异常。
修复后的循环式更新脚本:
{ "query": { "term": { "PublisherId": 349438 } }, "script": { "source": "int total = 0; if (ctx._source.Accounts != null) { for (def account : ctx._source.Accounts) { total += account.FollowersCount != null ? account.FollowersCount : 0; } } ctx._source.TotalSubscribers = total;", "lang": "painless" } }
更简洁的流式处理版本(兼容空值场景):
{ "query": { "term": { "PublisherId": 349438 } }, "script": { "source": "def total = ctx._source.Accounts?.stream()?.mapToInt(a -> a.FollowersCount != null ? a.FollowersCount : 0)?.sum() ?: 0; ctx._source.TotalSubscribers = total;", "lang": "painless" } }
这里用到了ES6.8支持的?.安全导航运算符,避免Accounts为null时直接抛出异常;同时对每个FollowersCount做空值兜底,默认取0。
为什么Request3能正常运行?
因为Request3只是遍历索引求和,没有访问FollowersCount属性,自然不会触发空指针异常。而Request1和2中直接访问account.FollowersCount,一旦遇到没有该字段的account对象,就会抛出空指针错误。
内容的提问来源于stack exchange,提问作者DedMorozzz
相关产品推荐
相关产品推荐

