与nosql的多对多关系(mongodb和mongoose)

与nosql的多对多关系(mongodb和mongoose),mongodb,mongoose,nosql,Mongodb,Mongoose,Nosql,我正在使用mongoDb和mongoose.js与多对多建立关系,我知道有很多选择,我的情况是: 我有两个文档,用户和项目,一个用户可以有多个项目,一个项目可以有多个用户,所以在我的例子中,我有4个选项: 1-项目文档中的id_用户数组 2-用户文档中id_项目的数组 3-项目文档中的id\u用户数组和 用户文档中的id\u项目 4-映射用户和项目关系的第三个表(如 关系数据库) 选项1和2不可用,因为,假设在选项1的场景中,如果我想从用户那里找到所有项目,我必须在用户的每个项目文档数组中查找此

我正在使用mongoDb和mongoose.js与多对多建立关系,我知道有很多选择,我的情况是:

我有两个文档,用户和项目,一个用户可以有多个项目,一个项目可以有多个用户,所以在我的例子中,我有4个选项:

1-项目文档中的id_用户数组

2-用户文档中id_项目的数组

3-项目文档中的id\u用户数组和 用户文档中的id\u项目

4-映射用户和项目关系的第三个表(如 关系数据库)

选项1和2不可用,因为,假设在选项1的场景中,如果我想从用户那里找到所有项目,我必须在用户的每个项目文档数组中查找此用户id(在每个项目中遍历此数组),这肯定不是一个好方法

选项3很好,但我必须进行某种交易,以确保两个文档都是书面的,这并不是那么糟糕,因为两个文档的读写能力都要比写的强得多

选项4更简单,因为当我向项目中添加一个用户时,只需添加一个具有两个id的新文档(我认为这是一个很好的解决方案,因为我不需要关心事务,这是一个很好的解决方案?)


那么,最好的解决方案是什么呢?

那么,解决方案1和2看起来并没有那么糟糕!若您为objectid数组编制索引,那个么就可以直接访问所需的内容

解决方案3看起来也不错,但解决方案4(不是真的)需要更多的查询,除非项目和用户之间的关系有很多变化,而不是它们本身


我更喜欢在数组上有索引的解决方案1。我想很多时候,您需要获取项目对象,这取决于用户或直接取决于id,因此
.find()
将满足您的所有需求。我认为用最少的信息来保持用户模式是不错的,它们看起来像是隔离对象,您可能需要它们用于其他目的。

相反,解决方案1和2是您最好的选择。当更新/创建频率与项目和用户的读取频率相比非常低时,可以考虑解决方案3,因为即使要更新/创建,它需要两个查询,阅读的方便性也可以弥补这一点


在解决方案1和2之间进行选择时,需要考虑读取频率。您是否会更频繁地需要某个用户的项目或使用某个项目,并据此进行选择。如果您觉得两者的频率相对相同,那么最好尽量减少用户对象的集群。无论您选择什么选项,请考虑在<代码> > ID ID>代码> s(项目或用户)的数组中保留<代码>索引>代码> 例如

userSchema = new Schema(
            {//otherstuff
               project_ids: [{type: Schema.Types.ObjectId, ref: 'Project'}})
              ...
            }) 
userSchema.index({'project_ids':1})

\u id
数组中保留索引将极大地提高查询速度,因为您担心这会带来巨大的开销

但是,只有当这个关系是一个重要的关系,并且有很多查询正在进行时,才保留
索引。如果这只是项目的一个次要功能,那么也可以在不使用索引的情况下执行

如果用户可以做很多事情并且有很多关系,那么在整个应用程序中,您将不断需要该用户对象,因此如果您的应用程序不是特定于项目的,那么最好不要将项目ID放入用户模式中。但是,由于我们只是在放置ID,所以不管怎么说,这并不是很大的开销。不用担心

两个数组上的Reg索引:是的,当然可以。但是,当您选择解决方案3时,您根本不需要索引,因为您不会执行查询来获取用户的项目列表或项目中的用户列表。解决方案3使阅读变得非常简单,但写作有点麻烦。但是,正如您提到的,您的用例涉及到
读>>写
,请使用解决方案3,但始终存在数据不一致的危险,您需要注意这一点

索引只是让事情变得更快。通过谷歌搜索一下。没什么特别的。在索引数组上查询比普通数组更有效。例如,假设您使用解决方案2。 将项目ID存储在“项目ID”字段中

您可以轻松获得用户的项目。这是直截了当的

但是为了获得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_id字段。假设我们有一个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都不好,因为两种方法的读取量几乎相同,但它们的写入频率非常低。解决方案3,我在考虑进行事务处理,以确保两个文档都填充了数据,如下所示:索引基本上是对文档进行排列,以便在索引字段上进行超快速查询。1表示升序索引,您可以使用-1获得降序索引。这在这里并不重要,但在数字和日期方面确实重要。确切地检查事务的陷阱(失败场景,即不一致)并评估您的选项。是的,解决方案1是我想使用的,问题是,我知道索引和普通数组一样更快、更高效,问题是,若我想为各自的用户查找项目,我必须查看所有项目文档,在每个项目文档中,遍历user_id数组进行检查,问题是,您明白吗?但是我认为这个解决方案更适合我的情况
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.