在MongoDb的子文档中更新数组中的特定文档

我有一个文档用户有一个模式为:

{ "_id" : ObjectId("57b2d706f61d04e8d99dd983"), "addressesAsVendor" : [ { "_id" : "V1", "addressLine1" : "al1", "addressLine2" : "al2", "street" : "street", "city" : "city", "country" : "IN", "pincode" : "490020", "location" : { "latitutde" : "lat1", "longitude" : "lon1" } }, { "_id" : "V2", "addressLine1" : "al1", "addressLine2" : "al2", "street" : "street", "city" : "city", "country" : "IN", "pincode" : "490020", "location" : { "latitutde" : "lat2", "longitude" : "lon2" } } ] } 

现在让我们假设我想用数据更新位于用户Id 57b2d706f61d04e8d99dd983中的addressesAsVendor数组的V1 id:

 { "addressLine1" : "al1 new", "addressLine2" : "al2 new", "street" : "street new", "city" : "city new", "country" : "IN new", "pincode" : "490020 new", "location" : { "latitutde" : "lat1 new", "longitude" : "lon1 new" } } 

所以新的用户文档将如下所示:

 { "_id" : ObjectId("57b2d706f61d04e8d99dd983"), "addressesAsVendor" : [ { "_id" : "V1", "addressLine1" : "al1 new", "addressLine2" : "al2 new", "street" : "street new", "city" : "city new", "country" : "IN new", "pincode" : "490020 new", "location" : { "latitutde" : "lat1 new", "longitude" : "lon1 new" } }, { "_id" : "V2", "addressLine1" : "al1", "addressLine2" : "al2", "street" : "street", "city" : "city", "country" : "IN", "pincode" : "490020", "location" : { "latitutde" : "lat2", "longitude" : "lon2" } } ] } 

MongoDb中如何实现这一点,保持多个地址的最佳方式是什么,这可以很容易地显示在用户的地址页面,也是最小的负载,我的意思是在需要的时候很容易访问。

请摆脱你的意见。 🙂

您可以使用位置$操作符来执行更新:

 var data = { "addressLine1" : "al1 new", "addressLine2" : "al2 new", "street" : "street new", "city" : "city new", "country" : "IN new", "pincode" : "490020 new", "location" : { "latitutde" : "lat1 new", "longitude" : "lon1 new" } }; collection.update( { "addressesAsVendor._id" : "V1" }, { "$set": { "addressesAsVendor.$": data } }, function(err, result) { if (err) return handleError(err); console.log(result); } ) 

上面的位置操作符保存了与查询匹配的数组中元素的索引(上例中为0)。 这意味着如果您事先知道元素的位置(在现实生活中几乎不可能),您可以将update语句更改为: { "$set": { "addressesAsVendor.0": data } }

由于位置$操作符充当匹配查询文档的第一个元素的占位符,并且数组字段必须作为查询文档的一部分出现,因此查询{ "addressesAsVendor._id" : "V1" }对于获取$运营商正常工作。

请注意位置$运算符(现在)只更新第一个相关文件,这是一个JIRA票据。


对于你的后续问题,寻求保持多个地址的最佳方式,这可以很容易地显示在用户的地址页面,也是最小的负载:

你现在的模式比创build一个单独的地址集合更好,因为单独的集合需要更多的工作,即查找用户+地址是两个查询,并且需要额外的工作,而上面的模式embedded式文档是简单和快速的(单一查找)。 插入和更新没有太大的区别。 因此,如果您需要select单个文档,需要对查询进行更多的控制,或者拥有大量的文档,则单独的集合是很好的。 当你想要整个文档时,embedded式文档是很好的,文档中embedded的addressesAsVendor $slice$slice ,或者根本没有地址。

一般来说,如果你有很多“地址”,或者如果他们很大,一个单独的集合可能是最好的。

较小和/或较less的文档往往是自然适合embedded的。

您可以使用updateOne (MongoDB查询)来更新文档。

NodeJS的等价物是:

 collection.update(criteria, update[[, options], callback]); 

请相应地更改对象ID。

 db.address.updateOne({ "_id" : ObjectId("57c04425c400a6b59c9bc1ee"), "addressesAsVendor._id" : "V1" }, { $set: { "addressesAsVendor.$.addressLine1" : "al1 new", "addressesAsVendor.$.addressLine2" : "al2 new", "addressesAsVendor.$.street" : "street new", "addressesAsVendor.$.city" : "city new", "addressesAsVendor.$.country" : "IN new", "addressesAsVendor.$.pincode" : "490020 new", "addressesAsVendor.$.location" : { "latitutde" : "lat1 new", "longitude" : "lon1 new" } } });