我与mongoDb和mongoose.js建立了很多人的关系,我知道有很多选择,我的情况是这样的:
我有两个文档,用户和项目,一个用户可以有很多项目,一个项目可以有很多用户,所以在我的情况下我有4个选项:
1 - 项目文档中的id_user数组。
2 - 用户文档中的id_project数组。
3 - 项目文档中的id_user数组&&一个阵列 用户文档中的id_project。
4 - 映射用户和项目关系的第三个表(如a 关系数据库)。
选项1和2不可用,因为,想象在选项1的场景中,如果我想从用户找到所有项目,我将不得不在用户的每个项目文档数组中查找此用户ID(在每个项目中遍历这个数组),这绝对不是一个好方法。
选项3很好,但是我必须进行某种交易以确保两个文件都会被写入,这并不是那么糟糕,因为这两个文件的阅读量都比写的要多得多
选项4更简单,因为当我向项目添加一个用户时,它只是添加一个带有两个id的新文档(我认为这是一个很好的解决方案,因为我不需要关心事务,这是一个很好的溶液?)
那么,什么是最好的解决方案?
答案 0 :(得分:8)
相反,解决方案1和2是你最好的选择。当更新/创建频率与项目和用户的读取频率相比非常少时,可以考虑解决方案3,因为即使更新/创建,它也需要两个查询,阅读的便利性将弥补这一点。
要在解决方案1和2中进行选择,您需要考虑读取频率。您是否需要更频繁地使用用户的项目或项目的使用并根据该选择进行选择。如果您认为两者的频率相对相同,则最好将用户对象保持为尽可能少的群集。无论选择何种选项,都应考虑在存储index
(项目或用户)的数组上保留_id
。
对于前。
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,所以它无论如何都不是很大的开销。无需担心。
两个阵列上的Reg索引:是的,你可以当然。但是,当您选择解决方案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会更好。在某些情况下,您可能需要没有项目的用户,但是没有用户要求项目的可能性非常低。但这取决于您的确切用例。
答案 1 :(得分:2)
解决方案1和2看起来不是那么糟糕!如果索引ObjectIds数组,则可以直接访问所需的内容。
解决方案3看起来也很好,但是4,不是真的,你需要更多的查询,除非你在项目和用户的关系之间有很多变化,但不是它们本身。
我更喜欢在数组上使用索引的解决方案1。我想很多时候你需要获取项目对象取决于用户或直接取决于id,所以.find()
会做你想做的一切。我认为用最少的信息保持用户架构并不坏,它们看起来像隔离对象,你可能需要它们用于其他目的。