查询MongoDb以从引用ID数组的集合中获取计数

时间:2016-10-13 07:49:41

标签: node.js mongodb mongoose mongodb-query aggregation-framework

我有3个收藏: 用户 2.帖子 3.行动

我的收藏品如下:

用户:

{ 
    "_id" : ObjectId("57ee65fef5a0c032877725db"), 
    "fbId" : "EAAXZA4sZCZBKmgBAKe0JpJPrp7utWME6xbHT9yFD", 
    "name" : "Aftab", 
    "email" : "xxxe@hotmail.com", 
    "gender" : "male", 
    "__v" : NumberInt(0), 
    "updatedAt" : ISODate("2016-10-10T05:11:35.344+0000"), 
    "score" : NumberInt(90)
}

操作:

{ 
    "_id" : ObjectId("57f7a0ba3a603627658afdd3"), 
    "updatedAt" : ISODate("2016-10-07T13:18:50.815+0000"), 
    "createdAt" : ISODate("2016-10-07T13:18:50.815+0000"), 
    "userId" : ObjectId("57ee65fef5a0c032877725db"), 
    "postId" : ObjectId("57f4b5e98899081203883a1b"), 
    "type" : "like"
}
{ 
    "_id" : ObjectId("57f7a0ba3a603627658afdd4"), 
    "updatedAt" : ISODate("2016-10-07T13:18:50.815+0000"), 
    "createdAt" : ISODate("2016-10-07T13:18:50.815+0000"), 
    "userId" : ObjectId("57ee65fef5a0c032877725db"), 
    "postId" : ObjectId("57f4b5d58899081203883a1a"), 
    "type" : "dismiss"
}

帖子:

{ 
    "_id" : ObjectId("57f24593e272b5199e9351b9"), 
    "imgFileLocation" : "http://xxxx/buybye-platform/uploads/image-1475495315229", 
    "description" : "cool cool", 
    "title" : "Bad Image ", 
    "userId" : ObjectId("57f21e3d0b787d0f7ad76dd0"), 
    "__v" : NumberInt(0)
}
{ 
    "_id" : ObjectId("57f4b5d58899081203883a1a"), 
    "imgFileLocation" : "http://xxx/buybye-platform/uploads/image-1475655125125", 
    "description" : "cool & cool", 
    "title" : "Good Image", 
    "userId" : ObjectId("57f21e3d0b787d0f7ad76dd0"), 
    "__v" : NumberInt(0)
}

用户可以创建帖子,其他用户可以对这些帖子执行操作

posts collection有一个userId的引用 和actions集合具有userId(执行该操作的人),postId(在哪个帖子上)和action-type(如/ dislike / dismiss)的引用

我需要查询以获取在特定用户帖子上执行的所有操作

我能够针对用户获取所有帖子,这非常简单并且是一个数组。现在我需要在这个帖子数组的每个帖子上执行所有操作。

1 个答案:

答案 0 :(得分:2)

如果您想要一个利用聚合框架的解决方案,您可以使用从MongoDB v3.2开始引入的$lookup阶段。

例如,如果要返回包含帖子详细信息的结果集以及在该特定帖子上执行的所有操作的数组,则可以运行以下聚合查询:

/*
 * QUERY #1
 */
db.posts.aggregate([
    {
        $lookup: {
            from: 'actions',
            localField: '_id',
            foreignField: 'postId',
            as: 'post_actions'
        }
    }
]);

/*
 * RESULT SET #1
 */
{
    "_id" : ObjectId("57ff4512a134e614a7178c1d"),
    "imgFileLocation" : "http://xxxx/buybye-platform/uploads/image-1475495315229",
    "description" : "cool cool",
    "title" : "Bad Image ",
    "userId" : ObjectId("57f21e3d0b787d0f7ad76dd0"),
    "__v" : 0,
    "post_actions" : [
        {
            "_id" : ObjectId("57ff4563a134e614a7178c1e"),
            "updatedAt" : ISODate("2016-10-07T13:18:50.815Z"),
            "createdAt" : ISODate("2016-10-07T13:18:50.815Z"),
            "userId" : ObjectId("57ee65fef5a0c032877725db"),
            "postId" : ObjectId("57ff4512a134e614a7178c1d"),
            "type" : "like"
        },
        {
            "_id" : ObjectId("57ff4564a134e614a7178c1f"),
            "updatedAt" : ISODate("2016-10-07T13:18:50.815Z"),
            "createdAt" : ISODate("2016-10-07T13:18:50.815Z"),
            "userId" : ObjectId("57ee65fef5a0c032877725db"),
            "postId" : ObjectId("57ff4512a134e614a7178c1d"),
            "type" : "share"
        }
    ]
}

否则,如果您只想检索特定帖子数组的操作,可以在聚合管道中添加$match阶段:

const postIdsArray = [
    ObjectId("57ff4512a134e614a7178c1d"),
    ObjectId("57ee65fef5a0c032877725db")
];

/*
 * QUERY #2
 */
db.posts.aggregate([
    {
        $match: {
            _id: {
                $in: postIdsArray
            }
        }
    },
    {
        $lookup: {
            from: 'actions',
            localField: '_id',
            foreignField: 'postId',
            as: 'post_actions'
        }
    }
]);

此外,如果您只想检索在帖子上执行的操作总数,可以添加$unwind阶段,然后$group所有结果:

/*
 * QUERY #3
 */
db.posts.aggregate([
    {
        $lookup: {
            from: 'actions',
            localField: '_id',
            foreignField: 'postId',
            as: 'post_actions'
        }
    },
    {
        $unwind: '$post_actions'
    },
    {
        $group: {
            _id: '$_id',
            posts: { $sum: 1 }
        }
    }
]);

/*
 * RESULT SET #3
 */
{ "_id" : ObjectId("57ff4512a134e614a7178c1d"), "posts" : 2 }

更新#1

如果您只想检索特定类型的操作(例如:喜欢,分享等),您可以在$match之后在汇总管道中添加额外的$unwind阶段在$lookup阶段检索的post_actions数组。

例如,第一个查询将变为:

/*
 * UPDATED QUERY #1
 */
db.posts.aggregate([
    {
        $lookup: {
            from: 'actions',
            localField: '_id',
            foreignField: 'postId',
            as: 'post_actions'
        }
    },
    {
        $unwind: '$post_actions'
    },
    {
        $match: {
            "post_actions.type": 'like'
        }  
    }
]);

第二个查询将成为:

const postIdsArray = [
    ObjectId("57ff4512a134e614a7178c1d"),
    ObjectId("57ee65fef5a0c032877725db")
];

/*
 * UPDATED QUERY #2
 */
db.posts.aggregate([
    {
        $match: {
            _id: {
                $in: postIdsArray
            }
        }
    },
    {
        $lookup: {
            from: 'actions',
            localField: '_id',
            foreignField: 'postId',
            as: 'post_actions'
        }
    },
    {
        $unwind: '$post_actions'
    },
    {
        $match: {
            "post_actions.type": 'like'
        }
    }
]);

第三个查询将成为:

/*
 * UPDATED QUERY #3
 */
db.posts.aggregate([
    {
        $lookup: {
            from: 'actions',
            localField: '_id',
            foreignField: 'postId',
            as: 'post_actions'
        }
    },
    {
        $unwind: '$post_actions'
    },
    {
        $match: {
            "post_actions.type": 'like'
        }
    },
    {
        $group: {
            _id: '$_id',
            posts: { $sum: 1 }
        }
    }
]);