我正在使用 mongoDb 和 mongoose.js 与多对多建立关系,我知道有很多选择,我的情况是这样的:
我有两个文档,用户和项目,一个用户可以有很多项目,一个项目可以有很多用户,所以在我的例子中我有 4 个选项:
1 - An array of id_user inside project document.
2 - An array of id_project inside user document.
3 - An array of id_user inside project document && An array of id_project inside user document.
4 - A third table mapping user and project relationship(like a relational database).
选项 1 和 2 不可用,因为,假设在选项 1 的场景中,如果我想查找用户的所有项目,我将不得不在用户的每个项目文档数组中查找此用户 ID(在每个项目中遍历这个数组),这绝对不是一个好方法。
选项 3 很好,但我必须进行某种交易以确保两个文档都被写入,这还不错,因为两个文档的读取量都比写入量多得多
选项 4 更简单,因为当我将一个用户添加到项目时,它只是添加一个具有两个 id 的新文档(我认为这是一个很好的解决方案,因为我不需要关心事务,这是一个很好的解决方案?)
那么,最好的解决方案是什么?
最佳答案
相反,解决方案 1 和 2 是您的最佳选择。当更新/创建频率与项目和用户的读取频率相比非常少时,可以考虑方案3,因为即使更新/创建需要两次查询,阅读的便利性将弥补这一点。
要在解决方案 1 和 2 中进行选择,您需要考虑读取频率。您会更频繁地需要用户的项目或项目的使用,并据此选择。如果您觉得两者的频率相对相同,则最好使用户对象尽可能少聚集。无论您选择什么选项,请考虑在存储 _id
(项目或用户)的数组上保留一个 index
。
例如
userSchema = new Schema(
{//otherstuff
project_ids: [{type: Schema.Types.ObjectId, ref: 'Project'}})
...
})
userSchema.index({'project_ids':1})
或
projectSchema = new Schema(
{//otherstuff
user_ids: [{type: Schema.Types.ObjectId, ref: 'User'}})
...
})
projectSchema.index({'user_ids':1})
在 _id
数组上保留索引将大大提高您的查询速度,避免您担心会产生大量开销。
但是只有当这个关系是一个重要的关系并且有很多查询正在进行时才保留index
。如果这只是您项目的一个附带功能,您也可以在 without
的情况下使用索引。
如果用户可以做很多事情并且有很多关系,那么您将在整个应用程序中不断需要该用户对象,因此如果您的应用程序不是特定于项目的,最好不要将项目 ID 放入用户架构。但是,由于我们只是放置 id,所以无论如何开销都不是很大。不用担心。
两个数组上的注册索引:是的,你当然可以。但是,当您选择解决方案 3 时,您根本不需要索引,因为您不会进行查询来获取用户的项目列表或项目中的用户列表。解决方案 3 使阅读变得非常容易,但编写起来有点麻烦。但是正如您提到的,您的用例涉及reading>>writing
,请使用解决方案 3,但始终存在数据不一致的危险,您需要注意。
索引只是让事情变得更快。通过the docs并做一些谷歌搜索。没有什么花哨。查询索引数组比普通数组更有效。例如。让我们假设您使用解决方案 2。 将项目 ID 存储在 project_ids 字段中。
您可以轻松获取用户的项目。这是直截了当的。
但是要获取 project1 的用户。你需要这样的查询。
User.find({project_ids:project._id},function(err,docs){
//here docs will be the list of the users of project1
})
//The above query might be slow if the user base is large.
//But it can be improved vastly by indexing the project_ids field in the User schema.
与解决方案 1 类似。每个项目都有 user_ids 字段。假设我们有一个 user1。 要获取用户的项目,我们执行以下查询
Project.find({user_ids:user1._id},function(err,docs){
//here docs will be the projects of user1
//But it can be improved vastly by indexing the user_ids field in the Project schema.
如果您正在考虑解决方案 1 与解决方案 2,我想解决方案 1 会更好。在某些情况下,您可能需要没有他的项目的用户,但需要没有用户的项目的可能性非常低。但这取决于您的具体用例。
https://stackoverflow.com/questions/25101386/