要做这种事情,您需要在聚合框架中使用
$cond
运算符。Spring Data MongoDB目前还没有实现这一点,而常见的
$group
操作也缺少许多内容,甚至只在
$project
下实现。
跟踪任何
$cond
支持的问题请参阅此处:
https://jira.spring.io/browse/DATAMONGO-861
对于世界上的其他人来说,它看起来像这样:
db.collection.aggregate([
{ "$match": { "_id": ObjectId("545b9fa0dd5318a4285f7ce7") } },
{ "$unwind": "$messages" },
{ "$group": {
"_id": "$_id",
"sent": {
"$sum": {
"$cond": [
{ "$eq": [ "$mesages.status", "sent" ] },
1,
0
]
}
},
"pending": {
"$sum": {
"$cond": [
{ "$eq": [ "$messages.status", "pending" ] },
1,
0
]
}
},
"done": {
"$sum": {
"$cond": [
{ "$eq": [ "$messages.status", "done" ] },
1,
0
]
}
}
}}
])
要在mongotemplate聚合下使这样的事情工作,您需要扩展聚合操作的类,该类可以从DBObject构建:
public class CustomGroupOperation implements AggregationOperation {
private DBObject operation;
public CustomGroupOperation (DBObject operation) {
this.operation = operation;
}
@Override
public DBObject toDBObject(AggregationOperationContext context) {
return context.getMappedObject(operation);
}
}
然后您可以将"$group"定义为DBObject
并在聚合管道中实现:
DBObject myGroup = (DBObject)new BasicDBObject(
"$group", new BasicDBObject(
"_id","$_id"
).append(
"sent", new BasicDBObject(
"$sum", new BasicDBObject(
"$cond", new Object[]{
new BasicDBObject(
"$eq", new Object[]{ "$messages.status", "sent"}
),
1,
0
}
)
)
).append(
"pending", new BasicDBObject(
"$sum", new BasicDBObject(
"$cond", new Object[]{
new BasicDBObject(
"$eq", new Object[]{ "$messages.status", "pending"}
),
1,
0
}
)
)
).append(
"done", new BasicDBObject(
"$sum", new BasicDBObject(
"$cond", new Object[]{
new BasicDBObject(
"$eq", new Object[]{ "$messages.status", "done"}
),
1,
0
}
)
)
)
);
ObjectId myId = new ObjectId("545b9fa0dd5318a4285f7ce7");
Aggregation aggregation = newAggregation(
match(Criteria.where("_id").is(myId)),
unwind("messges"),
new CustomGroupOperation(myGroup)
);
这使您能够创建一个与上面的shell表示基本相同的管道。
因此,目前看来,在某些操作和序列不受支持的情况下,最好的情况是实现一个类在AgggregationOperation接口上,可以将DBObject提供给它,或者通过自己的自定义方法从内部构造一个。
$cond
问题已经存在一段时间了。复杂分组和分组_id
值是“已知问题”。其中一些实现起来并不难作为方法。你可以随时捐出时间。我也应该考虑这个。 - Neil Lunnmessages.status=="Done"
和messages.status2=="Ready"
。 - Half Blood Princematch
和unwind
方法的实现。 - Half Blood Prince