0

HOUR_COUNTS 个集合包含 {docId, hour, count}

通过使用以下 mongodb 查询,我很容易获得 docId 的计数总和:

db.HOUR_COUNTS.aggregate(
    [
        {
            $match: { hour: { $gte: 10 } }
        },
        {
            $group: { _id: "$docId", total: { $sum: "$count" } }
        },
        { 
            $sort: { total: -1, _id: -1 }
        },
        {
            $limit: 20
        }
    ]
)

然后我可以得到以下结果:

{ "_id" : 6831, "total" : 6 }
{ "_id" : 6830, "total" : 6 }
{ "_id" : 6849, "total" : 4 }
{ "_id" : 6848, "total" : 4 }
{ "_id" : 6847, "total" : 3 }

现在是我使用 Spring Data 的时候了

我试图这样做,但它不会工作:

    Aggregation agg = newAggregation(
            match(where("hour").gte(0)),
            project("docId"),
            group("docId").sum("count").as("total"), 
            project("total").and("docId").previousOperation(), 
            sort(Sort.Direction.DESC, "total", "docId"),
            limit(20)
        );

错误是:

java.lang.IllegalArgumentException: Invalid reference 'count'!

因此,我想知道如何使查询在 Spring Data 上工作。谢谢你。

4

1 回答 1

2

为什么这会起作用?这才是你真正应该问自己的问题。

在聚合管道操作中,诸如$project$group仅“返回”您明确要求它们返回的字段之类的运算符。作为“管道”概念,只有前一个管道阶段的“输出”可用于下一个阶段及其后的阶段,除非可能再次修改。

因此,您在 Java 代码中编写的内容不等于您在 shell 中进行的实验。您尝试引用先前$project操作中排除的“字段”。所以不要那样做。您似乎对聚合管道中的实际优化方式有错误的看法:

    Aggregation agg = newAggregation(
        match(Criteria.where("hour").gte(10)),
        group("docId").sum("count").as("total"),
        sort(Sort.Direction.DESC, "total","docId"),
        limit(20)
    );

所以这实际上和你之前写的“一样”。您不需要额外的“项目”操作,它们不利于您的预期结果。

于 2014-08-19T11:03:51.007 回答