我希望仅在嵌入文档中没有密钥时才将新值插入到嵌入文档中。例如,我的文档最初是
{
name: "doc1",
embeddedDoc: {
a: 123,
b: 456
}
}
然后,如果我要“插入”{b: 789, c: 101}
,我希望结果为embeddedDoc: {a: 123, b: 456, c: 101}
(插入新的c
,不要触及现有的b
) 。有没有办法做到这一点?
到目前为止,我所拥有的最佳解决方案是在插入对象中为每个元素运行一个查询:
collection.update(
{"embeddedDoc.b": {$exists: false}},
{$set: {"embeddedDoc.b": 456}}
)
答案 0 :(得分:1)
我非常怀疑你可以为许多属性做2次查询。如果您有许多属性,则可以进行第一个查询以获取所有属性,然后知道您拥有的属性,找到缺少的属性作为设置差异。然后只更新缺少的属性。
因此,对于任意数量的属性,最终会得到2个查询和一个简单的应用程序逻辑。请注意,在高度繁忙的应用程序中,query1(find)和query2(update)之间可能会发生一些事情。
答案 1 :(得分:1)
就个人而言,我的文档中没有对象,而是数组。它不会解决不会过度覆盖数据的问题,但它确实可以解决"查找"在"键"使用"数据"可以编入索引。这将是一个很大的"如果您经常打算进行这类更新,则会有所不同。
{
"name": "Doc1",
"properties": [
{ "key": "a", "value": 123 },
{ "key": "b", "value": 456 }
]
}
所以使用" b"的新数据和" c",然后您可以进行这样的查询尝试:
db.collection.update(
{ "properties.key" { "$nin": [ "b", "c" ] } },
{
"$push": {
"properties": {
"$each": [
{ "key": "b", "value": 789 },
{ "key": "c", "value": 101 }
]
}
}
},
{ "multi": true }
)
如上所述,至少可以"可以"使用一个"键"用$exists
查找不能,你至少可以尝试"作为"第一次拍摄"进行此操作,如果文件确实满足给定条件,其中" b"和" c"," key"如果这些文件不受影响,那么这些文件就会受到影响。
后备案例当然是在这里针对每个属性单独进行尝试,但整个过程实际上并不难解决Bulk Operations:
var obj = { "b": 456, "c": 101 };
var keys = Object.keys(obj),
mapped = keys.map(function(key) {
return { "key": key, "value": obj[key] };
});
var bulk = intitializeOrderedBulkOp();
bulk.find({ "properties.key": { "$nin": keys } }).update({
"$push": { "properties": { "$each": mapped } }
});
keys.forEach(function(key) {
bulk.find({ "properties.key": { "$ne": key } }).update({
"$push": { "properties": { "key": key, "value": obj[key] } }
});
});
bulk.execute();
注意到如果第一个查询确实成功了,那么其他一切可能都是" no-op"。但是,如果你用" multi"就像这样,除非你已经知道要测试多少文件,否则你永远无法确定。因此,可能一次发送所有内容"比抱歉更安全" 。
所以它很简单,代码很简单,因批量操作而往返于服务器,并且效率很高"在查找数据以匹配条件,因为能够使用索引。
"丢弃合并"您想要实现的逻辑总是意味着多次更新。但是,如果你至少让这个过程变得有效,那么#34;尽可能地,这至少要担心一件事。