Spring Data MongoDB中的聚合总和

时间:2014-08-13 18:29:16

标签: mongodb spring-data spring-data-mongodb

我有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.我在这里需要项目运作吗?

由于

1 个答案:

答案 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"
         }
      }
   ]
}