1

我有一个集合,其中的文档都采用这种格式:

{"user_id": ObjectId, "book_id": ObjectId}

它代表了用户和书籍之间的关系,也是一对多的,也就是说,一个用户可以拥有多本书。

现在我得到了三个book_id,例如:

["507f191e810c19729de860ea", "507f191e810c19729de345ez", "507f191e810c19729de860efr"]

我想查询出拥有这三本书的用户,因为我想要的结果不是这个集合中的文档,而是一个新构建的数组user_id,看起来很复杂,我不知道如何查询,请帮助我。

笔记:

我不使用结构的原因如下:

{"user_id": ObjectId, "book_ids": [ObjectId, ...]}

是因为在我的系统中,书籍增加频繁,数量没有限制,也就是说用户可能阅读了上千本书,所以我觉得还是用传统的方式存储比较好。

这个问题不受MongoDB的限制,可以用关系数据库的思路来回答。

4

1 回答 1

2

使用常规find您无法取回拥有所有 book_id 的所有 user_id 字段,因为您对集合进行了规范化(将其展平)。

如果您使用聚合框架,您可以这样做:

db.collection.aggregate([
    {
        $match: {
            book_id: {
                $in: ["507f191e810c19729de860ea",
                      "507f191e810c19729de345ez",
                      "507f191e810c19729de860efr" ]
            }
        }
    },
    {
        $group: {
            _id: "$user_id",
            count: { $sum: 1 }
        }
    },
    {
        $match: {
            count: 3
        }
    },
    {
        $group: {
            _id: null,
            users: { $addToSet: "$_id" }
        }
    }
]);

它的作用是仅通过管道过滤与三个 book_id 值之一匹配的文档,然后按 user_id 分组并计算该用户获得的匹配数。如果他们得到三个,他们将传递到下一个管道操作,该操作将它们分组到一个 user_ids 数组中。此解决方案假定每个 'user_id,book_id' 记录只能在原始集合中出现一次。

于 2013-03-19T06:35:39.290 回答