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

时间:2016-08-26 13:09:22

标签: node.js 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 中实现这一目标,以及保留多个地址的最佳方式,可以在用户的​​“地址”页面中轻松显示,且负载最小,意思是在需要时很容易访问。

请发表您的意见。 :)

2 个答案:

答案 0 :(得分:2)

您可以使用位置$运算符进行更新:

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)。这意味着如果您事先知道元素的位置(在现实生活中几乎不可能),您只需将更新语句更改为:{ "$set": { "addressesAsVendor.0": data } }

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

请注意,位置$运营商(目前)仅更新第一个相关文档,此处有 JIRA 票证。

对于您的后续问题,该问题旨在找到保留多个地址的最佳方式,这些问题可以在用户的​​“地址”页面中轻松显示,并且负载最小:

您当前的架构比创建单独的地址集更好,因为单独的集合需要更多的工作,即查找用户及其地址是两个查询并需要额外的工作,而上述架构嵌入式文档简单快速(单一搜索)。插入和更新没有太大区别。因此,如果您需要选择单个文档,需要对查询进行更多控制或拥有大量文档,则单独的集合是很好的。如果您需要整个文档,包含嵌入式$slice的{​​{1}}或完全没有地址的文档,嵌入式文档就会很好。

作为一般规则,如果您有很多“地址”或者它们很大,那么单独的集合可能是最好的。

较小和/或较少的文档往往非常适合嵌入。

答案 1 :(得分:1)

您可以使用 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"
            }
    } });