jac*_*cob 4 java mongodb mongodb-query aggregation-framework spring-data-mongodb
我有一个文件看起来像这样的集合:
{
_id: "545b9fa0dd5318a4285f7ce7",
owner: "admin",
messages: [
{
id: "100",
status: "sent",
note: ""
},
{
id: "100",
status: "pending",
note: ""
},
{
id: "101",
status: "sent",
note: ""
},
{
id: "102",
status: "sent",
note: ""
},
{
id: "101",
status: "done",
note: ""
}
]
}
Run Code Online (Sandbox Code Playgroud)
(这只是一个简短的例子,在我的例子中,子数组非常大)
我需要查询集合并获取特定文档的一些统计信息.所以在这个例子中,如果我查询具有id:"545b9fa0dd5318a4285f7ce7"的doucment,我应该得到这个结果:
{
sent: 3,
pending: 1,
done: 1
}
Run Code Online (Sandbox Code Playgroud)
如何使用spring mongotemplate进行此类聚合?
要做这种事情,您需要$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
]
}
}
}}
])
Run Code Online (Sandbox Code Playgroud)
要在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);
}
}
Run Code Online (Sandbox Code Playgroud)
然后,您可以将"$ 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)
);
Run Code Online (Sandbox Code Playgroud)
这允许您提出一个与上面的shell表示基本相同的管道.
所以现在看来,在不支持某些操作和序列的情况下,最好的情况是在AgggregationOperation接口上实现一个类,该类可以提供DBObject,或者从您自己的自定义方法内部构造一个.
| 归档时间: |
|
| 查看次数: |
5376 次 |
| 最近记录: |