Mongodb点字段更新

1 javascript mongodb mongodb-query

我在 Mongo 中有以下架构:

\n\n
var OrderSchema = new Schema({\n    postcode: String,\n    ...\n    status: {\n        last_check: { type: Date },\n        date: Date,\n        code: String,\n        postnum: String,\n        text: String,\n        class: String\n    },\n});\n
Run Code Online (Sandbox Code Playgroud)\n\n

我有一个保存数据的函数(旧方法已注释):

\n\n
function save_order(data) {\n//    var order = new Order(data);\n//    var upsertData = order.toObject();\n//    delete upsertData._id;\n//    Order.findOneAndUpdate({postcode: order.postcode}, upsertData, {upsert: true}, function (err) {\n  Order.update({postcode: data.postcode}, {$set:data}, function (err) {\n    if (err) console.log('err');\n  });\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

这里传递给函数的数据示例:

\n\n
{ postcode: 'BV123456789BY',\n  status: \n   { last_check: 1413539153572,\n     code: '06',\n     postnum: '247431',\n     date: Thu Oct 16 2014 09:52:00 GMT+0300 (\xd0\x92\xd0\xbe\xd1\x81\xd1\x82\xd0\xbe\xd1\x87\xd0\xbd\xd0\xb0\xd1\x8f \xd0\x95\xd0\xb2\xd1\x80\xd0\xbe\xd0\xbf\xd0\xb0 (\xd0\xbb\xd0\xb5\xd1\x82\xd0\xbe)),\n     text: '06. \xd0\x9f\xd0\xbe\xd1\x81\xd1\x82\xd1\x83\xd0\xbf\xd0\xb8\xd0\xbb\xd0\xbe \xd0\xb2 \xd1\x83\xd1\x87\xd0\xb0\xd1\x81\xd1\x82\xd0\xbe\xd0\xba \xd0\xbe\xd0\xb1\xd1\x80\xd0\xb0\xd0\xb1\xd0\xbe\xd1\x82\xd0\xba\xd0\xb8 \xd0\xbf\xd0\xbe\xd1\x87\xd1\x82\xd1\x8b (247431) \xd0\xa1\xd0\xb2\xd0\xb5\xd1\x82\xd0\xbb\xd0\xbe\xd0\xb3\xd0\xbe\xd1\x80\xd1\x81\xd0\xba - 1' } }\n
Run Code Online (Sandbox Code Playgroud)\n\n

设置 status.class 的函数工作正常 - 它不会覆盖 status :

\n\n
function setByOrderId(id, data) {\n//   data = {'status.class': 'danger'}\n    Order.update({_id: id}, {$set: data}, function (err) {\n        if (err) console.log('err');\n    });\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

问题是,当我更新状态时,status.class 的值消失...\n我应该如何更新状态而不覆盖 status.code?谢谢。

\n

Nei*_*unn 5

当然可以,因为这正是您要求它做的事情。尽管有你的标题,但这里根本没有使用“点符号” 。如果您不打算覆盖现有属性,这当然是您想要做的。现在你只是替换整个对象,尽管你使用了$set where 除非你改变这里的结构基本上是多余的。

\n\n

要“解决”这个问题,您需要data首先操作您的对象。沿着这些思路:

\n\n
var newobj = {};\nObject.keys( data ).forEach(function(key) {\n    if ( typeof(data[key]) == "object" ) {\n       Object.keys( data[key] ).forEach(function(subkey) {\n           newobj[key + "." + subkey] = data[key][subkey];\n       });\n    } else {\n       newobj[key] = data[key];\n    }\n});\n
Run Code Online (Sandbox Code Playgroud)\n\n

newobj这为您提供了如下结构的输出:

\n\n
{\n    "postcode" : "BV123456789BY",\n    "status.last_check" : 1413539153572,\n    "status.code" : "06",\n    "status.postnum" : "247431",\n    "status.date" : ISODate("2014-10-17T11:28:20.540Z"),\n    "status.text" : "06. \xd0\x9f\xd0\xbe\xd1\x81\xd1\x82\xd1\x83\xd0\xbf\xd0\xb8\xd0\xbb\xd0\xbe \xd0\xb2 \xd1\x83\xd1\x87\xd0\xb0\xd1\x81\xd1\x82\xd0\xbe\xd0\xba \xd0\xbe\xd0\xb1\xd1\x80\xd0\xb0\xd0\xb1\xd0\xbe\xd1\x82\xd0\xba\xd0\xb8 \xd0\xbf\xd0\xbe\xd1\x87\xd1\x82\xd1\x8b (247431) \xd0\xa1\xd0\xb2\xd0\xb5\xd1\x82\xd0\xbb\xd0\xbe\xd0\xb3\xd0\xbe\xd1\x80\xd1\x81\xd0\xba - 1"\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

当然,您可以继续正常更新并让一切正常:

\n\n
Order.update({ "postcode": newobj.postcode}, { "$set": newobj }, function (err) {\n    if (err) console.log(err);\n});\n
Run Code Online (Sandbox Code Playgroud)\n\n

当然,您需要一些递归来实现更嵌套的结构,但这应该会给您一个总体思路。点表示法是可行的方法,但您需要实际使用它。

\n