如何知道聚合组具有上一个/下一个值?

时间:2019-02-20 16:46:02

标签: mongodb aggregation-framework

假设我有以下聚合管道:

db.getCollection('posts').aggregate([
    { $match: { _id: { $gt: "some id" }, tag: 'some tag' } },
    { $limit: 5 },
    { $group: { _id: null, hasNextPage: {??}, hasPreviousPage: {??} } }
])

因此,$match$limit阶段将导致所有带有标签some tag的帖子的子集。我怎么知道子集前后有帖子?

我猜,一种可能的方法是在$lethasPreviousPage中包含表达式(带有hasNextPage),该表达式将搜索少于_id的帖子分别为"some id"和大于$last: "$_id"。但是我不确定如何在$let中将组引用为变量。另外,也许还有其他更有效的方法。

1 个答案:

答案 0 :(得分:1)

您可以使用以下汇总:

db.posts.aggregate([
    { $match: { tag: 'some tag' } },
    { $sort: { _id: 1 } },
    {
        $facet: {
            data: [
                { $match: { _id: { $gt: 'some id' } } },
                { $limit: 5 }
            ],
            hasPreviousPage: [
                { $match: { _id: { $lte: 'some id' } } },
                { $count: "totalPrev" }
            ],
            hasNextPage: [
                { $match: { _id: { $gt: 'some id' } } },
                { $skip: 5 },
                { $limit: 1 }, // just to check if there's any element
                { $count: "totalNext" }
            ]
        }
    },
    {
        $unwind: { path: "$hasPreviousPage", preserveNullAndEmptyArrays: true }
    },
    {
        $unwind: { path: "$hasNextPage", preserveNullAndEmptyArrays: true }
    },
    {
        $project: {
            data: 1,
            hasPreviousPage: { $gt: [ "$hasPreviousPage.totalPrev", 0 ] },
            hasNextPage: { $gt: [ "$hasNextPage.totalNext", 0 ] }
        }
    }
])

要对您的集合$sort应用任何分页,以确定的顺序获得结果。在按tag排序和过滤的集合上,您可以运行$facet,该集合允许您应用多个子聚合。代表上一页和下一页的管道可以以$count结尾。 $facet中的每个子聚合都将返回一个数组,因此我们可以运行$unwind来获取嵌套文档,而不是hasPreviousPagehasNextPage的数组。这里需要选项preserveNullAndEmptyArrays,因为如果没有上一个/下一个文档,则MongoDB将从聚合管道中删除整个文档。在最后一步中,我们可以将子聚合转换为布尔值。