我在MongoDB中有一个聚合查询,当我在shell中直接运行它时,它会起作用。这是shell查询:
db.MyCollection.aggregate([
{$match: {_id: {$in: ['A', 'B', 'C']}}},
{$project: {"versions": "$nested.field.version"}},
{$unwind: "$versions"},
{$group: {_id: "$_id", "maxVersion": {$max: "$versions"}}}
])
正如您所看到的,这可以做到以下几点:
就像我说的那样,上面的查询已经有效了。我的问题是如何将其转换为Spring MongoDB语法。这是我的第一次尝试,不工作:
Aggregation aggregation = newAggregation(
match(Criteria.where("_id").in(listOfIds))
,project().and("versions").nested(bind("versions", "nested.field.version"))
,unwind("versions")
,group("_id").max("versions").as("maxVersion")
);
当我尝试在调试模式下运行代码时,我可以看到我实际上在newAggregation上得到IllegalArgumentException,说它无法评估。如果我用$ group子句注释掉这一行,那么我可以看到聚合变量的这个toString()表示,它揭示了$ project子句的问题:
{
"aggregate" : "__collection__" ,
"pipeline" : [
{ "$match" : { "_id" : { "$in" : [ "A" , "B" , "C"]}}} ,
{ "$project" : { "versions" : { "versions" : "$nested.field.version"}}} ,
{ "$unwind" : "$versions"}
]
}
显然,这与我的意图不符,所以我没有得到正确的语法。但TBH我发现Spring MongoOps语法非常直观,而且他们的文档也不是很好。
如果没有先调用nested()
,我就无法调用and()
方法。我认为这是主要的问题,因为它将那里的筑巢加倍。有没有Spring MongoOps英雄可以帮我正确编写等效的Java代码?
答案 0 :(得分:6)
$project
管道不是必需的,因为您仍然可以在嵌套字段上执行 $unwind
,因此此聚合管道可以产生与您当前的结果相同:
db.MyCollection.aggregate([
{
"$match": {
"_id": { "$in": ['A', 'B', 'C'] }
}
},
{ "$unwind": "$nested.field" },
{
"$group": {
"_id": "$_id",
"maxVersion": { "$max": "$nested.field.version" }
}
}
])
Spring Data MongoDB聚合等价物:
Aggregation agg = newAggregation(
match(Criteria.where("_id").in(ids)),
unwind("nested.field"),
group("_id").max("nested.field.version").as("maxVersion")
);
回到当前的聚合,您需要在nested.field
数组上 $unwind
,而不是nested.field.version
字段,因为那是一个字符串,而不是数组:
db.MyCollection.aggregate([
{$match: {_id: {$in: ['A', 'B', 'C']}}},
{$project: {"fields": "$nested.field"}},
{$unwind: "$fields"},
{$group: {_id: "$_id", "maxVersion": {$max: "$fields.version"}}}
])
Sprind Data MongoDB等价物看起来像:
Aggregation agg = newAggregation(
match(Criteria.where("_id").in(ids)),
project().and("nested.field").as("fields")
unwind("fields"),
group("_id").max("fields.version").as("maxVersion")
);
答案 1 :(得分:0)
在修正下划线错误之前使用map reduce方法。 喜欢:
GroupBy groupBy = GroupBy.key("user_id")
.initialDocument("{ total : 0, used : 0 }")
.reduceFunction("function( curr, result ){ result.total++; if(curr.status == 1) {result.used++;} result.userID = curr.user_id;");
GroupByResults<YourResult> yourResultInfo =
mongoTemplate.group(Criteria.where("user_id").in(user_ids),
"your_collection_name", groupBy, YourResult.class);
class YourResult{
private String userID;
private Long total = 0l;
private Long used = 0l;
// getter and setter`enter code here
}
答案 2 :(得分:0)
在聚合操作中执行字段引用验证时,Spring使用_作为数组的野生购物车,并拆分snake_case字段。
为避免验证,您可以使用以下MongoTemplate方法执行聚合,而不进行字段转换和验证。
public <O> AggregationResults<O> aggregate(Aggregation aggregation, String collectionName, Class<O> outputType)