我有MongoDB Page和Post集合。每个页面文档都有字段postIds,它是post Ids(String对象)的数组。我想使用聚合来计算每个页面的帖子数(=数组postIds中的元素数)。我编写了Mongo Shell聚合函数,它可以完全返回我想要的内容:
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个帖子,这是正确的。
现在我想使用Spring MongoDB Aggregation编写相同的内容,并编写了这个简单的JUnit测试:
/**
* 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查询:
2014-08-13 20:06:07,949 DEBUG [org.springframework.data.mongodb.core.MongoTemplate] - 执行聚合:
{
"aggregate":"page",
"pipeline":[
{
"$match":{
"pageId":"2210"
}
},
{
"$unwind":"$postIds"
},
{
"$group":{
"_id":"$_id",
"sum":{
"$sum":"$1"
}
}
}
]
}
问题: 正如您所看到的,差异在于$ 1的$ sum值。我需要传递1号而不是1号,但我不确定如何。 2.我在这里需要项目运作吗?
由于
答案 0 :(得分:12)
我终于弄明白了。关键是在Spring Data for MongoDB中使用count()聚合函数,它在本机Mongo shell中转换为1的和。这是我最后的JUnit测试:
/**
* 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;
}
所以最后这转换为以下本机聚合操作:
{
"aggregate":"page",
"pipeline":[
{
"$match":{
"_id":"2210"
}
},
{
"$unwind":"$postIds"
},
{
"$group":{
"_id":"$_id",
"nPosts":{
"$sum":1
}
}
},
{
"$project":{
"nPosts":1,
"pageId":"$_id"
}
}
]
}