Spring Data mongodb聚合框架:project()中的ConditionalOperators进行中位数计算
Posted
技术标签:
【中文标题】Spring Data mongodb聚合框架:project()中的ConditionalOperators进行中位数计算【英文标题】:Spring Data mongodb aggregation framework: ConditionalOperators in project() for median calculation 【发布时间】:2018-09-25 05:22:32 【问题描述】:在使用 Spring Data 2.0 的示例项目中,我试图计算具有以下格式的文档的温度中值:
"_id":ObjectId("5ad28e92e284e00bbc0a9479"),
"deviceId":"myId",
"time": ISODate("2018-04-21T23:28:18.632 Z"),
"temperature":10,
"_class":"com.github.paizo.monitorapi.model.Refrigerator"
从here 我抓取一个聚合管道来计算我转换为以下 Spring Data 聚合的中值:
final Aggregation aggregation = newAggregation(
match(
Criteria.where(DEVICE_ID_FIELD).is(deviceId)
),
group().count().as("count").push(sensorValueField).as("values"),
unwind("values"),
sort(Sort.Direction.ASC, "values"),
project("count", "values")
.andExpression("(count) / 2").as("midpoint"),
project("count", "values", "midpoint")
.and(floor).as("low")
.and(ceil).as("high"),
group()
.push("values").as("values")
.avg("high").as("high")
.avg("low").as("low"),
project()
.and(beginValue).as("beginValue")
.and(endValue).as("endValue"),
//FIXME if ODD => v1 == v2 then return v1 else v1 != v2 => return average(v1,v2)
project().and(
ConditionalOperators.when(Criteria.where("beginValue").ne("endValue"))
.then("beginValue")
.otherwiseValueOf("(beginValue + endValue) / 2")
)
);
我试图在最后一个project()
中进行最终值检查的计算中可能出现的错误的一部分。 无论我在ConditionalOperators.when()
中写什么,生成的项目都是空的:
"aggregate":"refrigerator",
"pipeline":[
"$match":
"deviceId":"myId"
,
"$group":
"_id":null,
"count":
"$sum":1
,
"values":
"$push":"$temperature"
,
"$unwind":"$values"
,
"$sort":
"values":1
,
"$project":
"count":1,
"values":1,
"midpoint":
"$divide":[
"$count",
2
]
,
"$project":
"count":1,
"values":1,
"midpoint":1,
"low":
"$floor":"$midpoint"
,
"high":
"$ceil":"$midpoint"
,
"$group":
"_id":null,
"values":
"$push":"$values"
,
"high":
"$avg":"$high"
,
"low":
"$avg":"$low"
,
"$project":
"beginValue":
"$arrayElemAt":[
"$values",
"$low"
]
,
"endValue":
"$arrayElemAt":[
"$values",
"$high"
]
,
"$project":
],
"cursor":
"batchSize":2147483647
导致错误的原因:
org.springframework.data.mongodb.UncategorizedMongoDbException: Command failed with error 40177: 'Invalid $project :: caused by :: specification must have at least one field' on server localhost:27017. The full response is "ok" : 0.0, "errmsg" : "Invalid $project :: caused by :: specification must have at least one field", "code" : 40177, "codeName" : "Location40177" ; nested exception is com.mongodb.MongoCommandException: Command failed with error 40177: 'Invalid $project :: caused by :: specification must have at least one field' on server localhost:27017. The full response is "ok" : 0.0, "errmsg" : "Invalid $project :: caused by :: specification must have at least one field", "code" : 40177, "codeName" : "Location40177"
我对最后一个project()
做错了什么?是 Spring 数据问题吗?
【问题讨论】:
【参考方案1】:回答我自己的问题,也许它可以帮助别人。
原来$project
没有生成是因为project.and(...)
后面缺少as()
;
以下示例为条件运算符正确生成$project
:
project().and(ConditionalOperators.when(Criteria.where("beginValue").ne("endValue"))
.then("beginValue")
.otherwiseValueOf("(beginValue + endValue) / 2")).as("lowViewsQuestion")
【讨论】:
以上是关于Spring Data mongodb聚合框架:project()中的ConditionalOperators进行中位数计算的主要内容,如果未能解决你的问题,请参考以下文章
Spring Data MongoDB:如何用 Spring Aggregation 描述聚合 $merge?
无法使用 Spring Data JPA 执行聚合函数并获取结果
使用 mongoTemplate 在 spring-data-mongo Java 中进行 Mongo 聚合查询
将 mongodb 聚合查询翻译成 Java/Kotlin Spring Data