Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/mongodb/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Database MongoDB中的双向嵌入与单向嵌入(多对多)_Database_Mongodb_Mongoose_Database Design_Nosql - Fatal编程技术网

Database MongoDB中的双向嵌入与单向嵌入(多对多)

Database MongoDB中的双向嵌入与单向嵌入(多对多),database,mongodb,mongoose,database-design,nosql,Database,Mongodb,Mongoose,Database Design,Nosql,在MongoDB中建模N:M关系时,如果使用双向嵌入而不是单向嵌入有意义,我想与您讨论一下 比如说,我们有两个实体:一个产品可以属于许多(少数)类别,一个类别可以有许多(很多)产品 双向嵌入 如果我们使用这种方法,我们的类别将如下所示: { _id: 1, name: "Baby", products: [2] } { _id: 2, name: "Electronics", products: [1, 2] } 和产品: { _id: 1, name: "HD

在MongoDB中建模N:M关系时,如果使用双向嵌入而不是单向嵌入有意义,我想与您讨论一下

比如说,我们有两个实体:一个产品可以属于许多(少数)类别,一个类别可以有许多(很多)产品

双向嵌入 如果我们使用这种方法,我们的类别将如下所示:

{
  _id: 1,
  name: "Baby",
  products: [2]
}
{
  _id: 2,
  name: "Electronics",
  products: [1, 2]
}
产品

{
  _id: 1,
  name: "HDMI Cable",
  categories: [2]
}
{
  _id: 2,
  name: "Babyphone",
  categories: [1, 2]
}
查询: 如果我们想要获取属于特定类别的产品:

const category=categoriesCollection.findOne({name:“Electronics”});
const products=productsCollection.find({u id:{$in:category.products}}).toArray();
如果我们希望获取属于特定产品的类别:

const product=productsCollection.findOne({name:“Babyphone”});
const categories=categoriesCollection.find({u id:{$in:product.categories}}).toArray();
单向嵌入 因为一个产品可能只属于两个或三个类别,但一个类别可以有数百万个产品,我会将这些类别嵌入到产品中,而不是反过来。因此,我们可以确定,我们永远不会达到16 MB的最大文档大小

我们的产品外观与上述相同,但类别不再有“产品”字段

如果我们希望获取特定产品的类别,我们的查询与上面的查询相同:

const product=productsCollection.findOne({name:“Babyphone”});
const categories=categoriesCollection.find({u id:{$in:product.categories}}).toArray();
另一方面,如果我们获取特定类别的产品,我们的查询将更改为:

const category=categoriesCollection.findOne({name:“Electronics”});
const products=productsCollection.find({categories:category.\u id}).toArray();
在我们的产品系列中,我们在categories数组上放置了一个(多键)索引,因此性能应该可以

我的结论 对我来说,单向嵌入似乎是更好的解决方案,因为我们不会达到最大文档大小,同时与双向嵌入方法相比没有任何(?)缺点。为什么会有人想做双向嵌入?我错过什么了吗?性能方面,它应该几乎相同,还是没有


你觉得怎么样?

实际上还有一个完全不嵌入的选项,第三个集合只保留productId和categoryId。请检查我的答案,我举了一个多对多关系的例子。如果这对你有帮助,你可以在那里投票支持我的答案。@SuleymanSah这样我们就可以模仿RDBMS,不是吗?在您编写的代码中:''const result=await Patient.findById(req.params.id).populate({path:“检查”,populate:{path:“hospitalId”}});这将导致对数据库的3个请求(每个populate()添加一个),而对于嵌入,我们只需要两个请求,因此嵌入的性能会更好。还是我遗漏了什么?Adam在这一部分,我们可以使用聚合只进行一次db访问,真正的优势是,我们只需一个简单的代码就可以添加、更新或删除一个关系,只需一个操作。@SuleymanSah是的,使用$lookup而不是Mongoose populate(),我们就可以得到一个“真正的”连接,因此我们只需要一个请求。但接下来我们面临另一个问题:我们从聚合中获得的不再是一个患者模型对象,我们必须在Mongoose中定义一些适合的输出模型。总之,这对我来说一点也不容易。此外,如果我们只嵌入ObjectId,那么创建、更新或删除也不会太复杂?无需为聚合的响应定义mongoose模型。我们可以将结果返回给客户。