elasticsearch - 比较嵌套字段的总和
问题描述
我正在尝试创建将嵌套属性与非嵌套属性进行比较的请求
映射:
{
"mappings": {
"publishers": {
"properties": {
"Accounts": {
"type": "nested",
"properties": {
"FollowersCount": {
"type": "long"
}
}
},
"TotalSubscribers": {
"type": "long"
}
}
}
}
}
我想查找 Accounts.FollowersCount 的总和不等于 TotalSubscribers 的文档。
怎么做?
PS:我正在尝试创建这样的东西:
{
"_source": [
"TotalSubscribers",
"Accounts.FollowersCount"
],
"query": {
"bool": {
"filter": {
"script": {
"script": {
"source": "int total = 0; for (int i = 0; i < doc['Accounts'].length; ++i) {total += doc['Accounts'][i].FollowersCount;} return total == doc['TotalSubscribers'];",
"lang": "painless"
}
}
}
}
}
}
但它不起作用。当我将脚本移动到嵌套块中时,同样的问题。然后我无法访问 TotalSubscribers
更新 1:ES 版本 = 6.8
请求1:
{
"query": {
"term": {
"PublisherId": 349438
}
},
"script": {
"source": "ctx._source.TotalSubscribers = ctx._source.Accounts.stream().map(a -> a.FollowersCount).collect(Collectors.summingInt(Integer::intValue));"
}
}
错误:
{
"error": {
"root_cause": [
{
"type": "script_exception",
"reason": "runtime error",
"script_stack": [
"java.util.stream.Collectors.lambda$summingInt$11(Collectors.java:467)",
"java.util.stream.ReduceOps$3ReducingSink.accept(ReduceOps.java:169)",
"java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193)",
"java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1382)",
"java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:482)",
"java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:472)",
"java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)",
"java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)",
"java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499)",
"a -> a.FollowersCount).collect(Collectors.summingInt(Integer::intValue));",
" ^---- HERE"
],
"script": "ctx._source.TotalSubscribers = ctx._source.Accounts.stream().map(a -> a.FollowersCount).collect(Collectors.summingInt(Integer::intValue));",
"lang": "painless"
}
],
"type": "script_exception",
"reason": "runtime error",
"script_stack": [
"java.util.stream.Collectors.lambda$summingInt$11(Collectors.java:467)",
"java.util.stream.ReduceOps$3ReducingSink.accept(ReduceOps.java:169)",
"java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193)",
"java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1382)",
"java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:482)",
"java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:472)",
"java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)",
"java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)",
"java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499)",
"a -> a.FollowersCount).collect(Collectors.summingInt(Integer::intValue));",
" ^---- HERE"
],
"script": "ctx._source.TotalSubscribers = ctx._source.Accounts.stream().map(a -> a.FollowersCount).collect(Collectors.summingInt(Integer::intValue));",
"lang": "painless",
"caused_by": {
"type": "null_pointer_exception",
"reason": null
}
},
"status": 500
}
请求2:
{
"query": {
"bool": {
"must": [
{
"term": {
"PublisherId": 349438
}
}
]
}
},
"script": {
"source": "int total = 0; for(int i=0;i<=ctx._source.Accounts.size()-1;i++){total += ctx._source.Accounts[i].FollowersCount} ctx._source['TotalSubscribers'] = total"
}
}
也有错误,靠近“total += ctx._source.Accounts[i].FollowersCount
请求3:
{
"query": {
"bool": {
"must": [
{
"term": {
"PublisherId": 349438
}
}
]
}
},
"script": {
"source": "int total = 0; for(int i=0;i<=ctx._source.Accounts.size()-1;i++){total += i} ctx._source['TotalSubscribers'] = total"
}
}
工作正常,更新后 totalSubscribers == count Account items。但是需要获取 Accounts 属性,而不是我...
解决方案
这可以通过script
查询来解决,但由于无法访问script
查询中的嵌套文档,因此您必须以不同的方式进行。在这些情况下,在顶层添加一个包含 的总和的新字段总是容易得多FollowersCount
,您可以将其命名为TotalFollowersCount
。
首先,您需要使用_update_by_query
端点创建该字段,如下所示:
POST your-index/_update_by_query
{
"script": {
"source": """
ctx._source.TotalFollowersCount = ctx._source.Accounts
.stream()
.map(a -> a.FollowersCount ?: 0)
.collect(Collectors.summingInt(Integer::intValue));
"""
}
}
然后您可以使用script
查询来查找有问题的文档:
GET your-index/_search
{
"query": {
"script": {
"script": "doc.TotalFollowersCount.value != doc.TotalSubscribers.value"
}
}
}
推荐阅读
- css - 媒体查询和 vuejs
- c - `"apue.h"`不是全局环境 PATH ,但程序可以检索它
- node.js - 支付成功后如何跳转到外部网页?
- python-2.7 - 如何选择两个不同列的随机日期时间?
- c++ - 如何使用两个不同的参数值调用我的模拟方法两次
- python - How to sum certain numbers in a python list?
- c++ - 如何使函数模板成为测试的参数?
- javascript - 触发 window.open 作为 ajax 完成
- matlab - 对称矩阵乘积不是对称的
- mysql - MySQL Workbench - 带有外键约束的错误 ERROR 1215 (HY000)