Spring Data MongoDB中的聚合求和

5

我有 MongoDB 的页面和文章集合。每个页面文档都有一个 postIds 字段,它是一组 post Ids(字符串对象)。我想使用聚合来计算每个页面的文章数(即数组 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. 如您所见,不同之处在于 $1 的 $sum 值。我需要传递数字 1 而非 $1,但我不确定如何操作。 2. 我需要在这里使用投影操作吗?

谢谢。

1个回答

17

我最终弄清楚了。关键是在Spring Data for MongoDB中使用count()聚合函数,它将转换为Mongo原生shell中的sum increments by 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"
         }
      }
   ]
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接