相反,解决方案 1 和 2 是您的最佳选择。当更新/创建频率与项目和用户的读取频率相比非常少时,可以考虑解决方案3,因为即使更新/创建需要两次查询,阅读的便利性将弥补这一点。
要在解决方案 1 和 2 中进行选择,您需要考虑读取频率。您是否需要更频繁地使用用户的项目或项目的使用并据此选择。如果您觉得两者的频率相对相同,则最好使用户对象尽可能少聚集。无论您选择什么选项,请考虑在存储_ids(项目或用户)的阵列上保留一个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 更好。在某些情况下,您可能需要没有他的项目的用户,但需要没有用户的项目的可能性非常低。但这取决于您的具体用例。