【问题标题】:Query MongoDb to get counts from collection on array of reference id查询 MongoDb 以从引用 id 数组的集合中获取计数
【发布时间】:2016-10-13 07:49:41
【问题描述】:

我总共有 3 个收藏: 1. 用户 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 集合有 userId 的引用 并且操作集合具有 userId(谁执行了该操作)、postId(在哪个帖子上)和 action-type(喜欢/不喜欢/解雇)的 ref

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

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

【问题讨论】:

  • 您是否愿意使用集合中的一些示例文档和所需聚合的预期输出来更新您的问题?这有助于澄清问题并鼓励提供高质量的答案。
  • 你运行的是哪个 MongoDB 版本?
  • mongodb v3.2 @Styvane

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


【解决方案1】:

如果您想要一个利用聚合框架的解决方案,您可以使用从 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 检索到 post_actions 数组之后在$lookup 阶段。

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

/*
 * 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 }
        }
    }
]);

【讨论】:

  • 完美运行。我如何获得对该特定帖子的特定操作的总数?说“喜欢”或“不喜欢”
  • @HaroonKhan 我已经更新了所有 3 个示例查询的答案以满足您的要求。看看吧:)
猜你喜欢
  • 2021-04-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-15
  • 1970-01-01
  • 2021-10-01
  • 2019-06-15
  • 2013-07-17
相关资源
最近更新 更多