Spring Data MongoDB中的聚合总和 [英] Aggregation sum in Spring Data MongoDB
问题描述
我有MongoDB页面和帖子集合.每个页面文档都有一个字段postIds,它是发布ID(字符串对象)的数组.我想使用聚合来计算每个页面的帖子数(=数组postIds中的元素数).我写了Mongo Shell聚合函数,该函数恰好返回了我想要的:
I have MongoDB Page and Post collections. Each page document has field postIds which is array of post Ids (String objects). I want to use aggregation to count number of posts (=number of elements in array postIds) for each page. I wrote Mongo Shell aggregation function which returns exactly what I want:
db.page.aggregate([
{$unwind : '$postIds'},
{$group : {_id: '$_id', 'sum': { $sum: 1}}}
])
并返回以下结果:
{ "_id" : "3", "sum" : 3 }
{ "_id" : "2", "sum" : 3 }
这意味着ID 3的页面有3个帖子,ID 2的页面也有3个帖子,
This means that page with id 3 has 3 posts, and page with id 2 has 3 posts as well, which is correct.
现在,我想使用Spring MongoDB Aggregation编写相同的代码,并编写了这个简单的JUnit测试:
Now I wanted to write same using Spring MongoDB Aggregation, and wrote this simple JUnit test:
/**
* Test page posts count
*/
@Test
public void testPagePostsCount() throws Exception{
MongoTemplate template = repository.getMongoTemplate();
Page page = new Page();
page.setPageId("2210");
page.setUserId("azec");
List<String> postList = new ArrayList<String>();
postList.add("53eb1a560efbe048c7ea698d");
postList.add("53eb1a6b0efbe048c7ea698e");
page.setPostIds(postList);
template.save(page);
Aggregation agg = newAggregation(
match(Criteria.where("pageId").is("2210")),
unwind("postIds"),
group("_id").sum("1").as("sum")
//project("$sum").and("pageId").previousOperation()
);
AggregationResults<PostCount> results = template.aggregate(agg, "page", PostCount.class);
List<PostCount> postCount = results.getMappedResults();
System.out.println("Done!");
}
但是,此聚合查询返回此本机Mongo查询:
However, this aggregation query returns this native Mongo query:
2014-08-13 20:06:07,949调试[org.springframework.data.mongodb.core.MongoTemplate]-执行聚合:
2014-08-13 20:06:07,949 DEBUG [org.springframework.data.mongodb.core.MongoTemplate] - Executing aggregation:
{
"aggregate":"page",
"pipeline":[
{
"$match":{
"pageId":"2210"
}
},
{
"$unwind":"$postIds"
},
{
"$group":{
"_id":"$_id",
"sum":{
"$sum":"$1"
}
}
}
]
}
问题: 1.如您所见,其差额是$ sum值$ 1.我需要传递数字1而不是$ 1,但我不确定如何传递. 2.我需要在这里进行项目运营吗?
Questions: 1. As you can see, the difference is with the $sum value of $1. I need to pass there number 1 instead of $1, but I am not sure how. 2. Do I need project operation here?
谢谢
推荐答案
我终于弄清楚了.关键是在Spring Data for MongoDB中使用count()聚合函数,该函数转换为在本机Mongo Shell中以1为增量的总和.这是我最后的JUnit测试:
I have figured this out finally. The key is to use count() aggregation function in Spring Data for MongoDB, which translates to sum increments by 1 in native Mongo shell. This is my final JUnit Test:
/**
* Test page posts count
*/
@Test
public void testPagePostsCount() throws Exception{
MongoTemplate template = repository.getMongoTemplate();
Page page = new Page();
page.setPageId("2210");
page.setUserId("azec");
List<String> postList = new ArrayList<String>();
postList.add("53eb1a560efbe048c7ea698d");
postList.add("53eb1a6b0efbe048c7ea698e");
page.setPostIds(postList);
template.save(page);
Aggregation agg = newAggregation(
match(Criteria.where("_id").is("2210")),
unwind("postIds"),
group("_id").count().as("nPosts"),
project("nPosts").and("_id").as("pageId")
);
AggregationResults<PostCount> results = template.aggregate(agg, "page", PostCount.class);
List<PostCount> postCount = results.getMappedResults();
Assert.assertTrue(!postCount.isEmpty());
Assert.assertTrue(postCount.get(0).nPosts == 2);
Assert.assertTrue(postCount.get(0).pageId.equals("2210"));
}
private class PostCount {
String pageId;
int nPosts;
}
所以最终,这转化为以下本机聚合操作:
So finally this translates to following native aggregation operation:
{
"aggregate":"page",
"pipeline":[
{
"$match":{
"_id":"2210"
}
},
{
"$unwind":"$postIds"
},
{
"$group":{
"_id":"$_id",
"nPosts":{
"$sum":1
}
}
},
{
"$project":{
"nPosts":1,
"pageId":"$_id"
}
}
]
}
这篇关于Spring Data MongoDB中的聚合总和的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!