我认为商店有两种类型的结构。产品如数据库
第一
ShopSchema = new Schema({
product_ids:[Schema.Types.ObjectId],
})
ProductSchema = new Schema({
product_name:String,
})
第二
ShopSchema = new Schema({
})
ProductSchema = new Schema({
shop_id:Schema.Types.ObjectId,
product_name:String,
})
第一个解决方案与第二个解决方案相比有一个干净的产品集合,产品集合中的每个文档都有一个shop_id字段(我认为这种浪费空间),但通过第一个结构得到所有产品可能会很痛苦,而第二个解决方案是很容易。
所以我想知道哪一个是最好的。或者你有更好的解决方案吗?
答案 0 :(得分:1)
第二个版本对大多数用例来说效率更高。非规范化是使用NoSQL持久性解决方案的游戏的名称。目标是尽可能少地在尽可能少的查询中获取所需的数据。这通常需要重复数据并处理在重复数据发生变化时必须更新大量文档的潜在麻烦。
例如,如果您希望在网页上显示该信息,您甚至可能必须将商店名称添加到产品文档中,因为如果不这样做,您仍然最终不得不查询商店馆藏。鉴于商店名称不易改变,应该相对头痛,但在设计架构时,您必须考虑这些事项。从您的用例开始,在设计时尽量减少。
答案 1 :(得分:1)
问自己以下问题:您是否可以在多个商店销售相同的产品?
如果答案为否,那么您可以认为shop_id
是商店的财产,您提供的第二个选项应该是有效的解决方案。
如果答案是肯定的,那么您需要能够将产品映射到多个商店。如果您要使用第二种设计,则需要多次复制一个产品对象,每个商店销售一次,这相当于您可以调用的新模式ProductInShop
。
请注意,您仍然有两个非常有效的选项来建模。您可以1)将product_ids
属性添加到ShopSchema
或2)将shop_ids
属性添加到ProductSchema
。
我猜测通过节省空间你也意味着规范化数据。与关系数据库不同,在文档数据库中,您通常倾向于避免规范化,而是尽可能地去规范化。例如:在关系数据库中,您通常会将其添加为包含列shop_id
和product_id
的新表。在像MongoDB这样的文档数据库中,您通常应该尽可能地将嵌入到单个文档中以避免“文档连接”。
还有一个关于猫鼬的说明。如果您想利用Mongoose的populate,请另外提供对集合名称的明确引用。例如:
var ShopSchema = new Schema({
product_ids: [{ type: Schema.Types.ObjectId, ref: 'Product' }]
});
通过这种方式,您可以使用Mongoose “找到所有商店和每个商店出售的所有产品”:
Shop.find().populate('product_ids').exec(function (err, shops) {
// ...
});