MongoDB:如何插入一个子文档?

我在我的MEAN项目中使用子文档来处理每个订单的订单和项目。

这些是我的(简化的)模式:

var itemPerOrderSchema = new mongoose.Schema({ itemId: String, count: Number }); 
 var OrderSchema = new mongoose.Schema({ customerId: String, date: String, items: [ itemPerOrderSchema ] }); 

要在itemPerOrderSchema数组中插入项目,我目前的做法是:

 var orderId = '123'; var item = { itemId: 'xyz', itemsCount: 7 }; Order.findOne({ id: orderId }, function(err, order) { order.items.push(item); order.save(); }); 

问题是,我显然希望每个itemId一个项目,这样我就可以获得每个项目的许多子文件…
一个解决scheme可能是遍历所有order.items ,但这不是最优的,当然( order.items可以我很多 …)。 查询order.items时可能会出现同样的问题

问题是:如何在itemPerOrderSchema数组中插入项目,而不必遍历订单上已插入的所有项目?

如果你可以使用一个对象而不是数组作为项目,也许你可以改变你的模式一点一个查询更新。

像这样的东西:

 { customerId: 123, items: { xyz: 14, ds2: 7 } } 

所以,每个itemId是对象中的一个键,而不是数组中的一个元素。

 let OrderSchema = new mongoose.Schema({ customerId: String, date: String, items: mongoose.Schema.Types.Mixed }); 

然后更新您的订单是非常简单的。 假设您想要将3个项目编号“xyz”添加到客户123。

 db.orders.update({ customerId: 123 }, { $inc: { 'items.xyz': 3 } }, { upsert: true }); 

即使客户没有条目,在这里传递upsert来创build订单。

这个缺点:

  • 如果你使用聚合框架,要么迭代你的项目是不可能的,或者如果你有一个有限的,已知的itemIds集合,那么非常详细。 你可以使用mapReduce来解决这个问题,这可能会稍微慢一些,这取决于你有多less人,所以YMMB。

  • 客户端上没有干净的items数组。 你可以用任何一个客户端解决这个问题(一个简单的let items = Object.keys(order.items).map(key => ({ key: order.items[key] }));或者用一个mongoose的虚拟域或schema.path(),但这可能是另一个问题,已经回答了。

首先,可能需要将orderId添加到itemPerOrderSchema,因为orderId和itemId的组合将使logging具有唯一性。

假设orderId被添加到itemPerOrderSchema,我会build议以下实现:

 function addItemToOrder(orderId, newItem, callback) { Order.findOne({ id: orderId }, function(err, order) { if (err) { return callback(err); } ItemPerOrder.findOne({ orderId: orderId, itemId: newItem.itemId }, function(err, existingItem) { if (err) { return callback(err); } if (!existingItem) { // there is no such item for this order yet, adding a new one order.items.push(newItem); order.save(function(err) { return callback(err); }); } // there is already item with itemId for this order, updating itemsCount itemPerOrder.update( { id: existingItem.id }, { $inc: { itemsCount: newItem.itemsCount }}, function(err) { return callback(err); } ); }); }); } addItemToOrder('123', { itemId: '1', itemsCount: 7 }, function(err) { if (err) { console.log("Error", err); } console.log("Item successfully added to order"); }); 

希望这可能有帮助。