Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/mongodb/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Mongodb 仅在嵌入文档中插入新属性_Mongodb_Mongodb Query - Fatal编程技术网

Mongodb 仅在嵌入文档中插入新属性

Mongodb 仅在嵌入文档中插入新属性,mongodb,mongodb-query,Mongodb,Mongodb Query,我只想在嵌入文档还没有密钥的情况下,将新值插入到嵌入文档中。例如,我的文档最初是 { name: "doc1", embeddedDoc: { a: 123, b: 456 } } 然后,如果我要“插入”{b:789,c:101},我希望结果具有嵌入的doc:{a:123,b:456,c:101}(插入新的c,不要触摸现有的b)。有办法做到这一点吗 到目前为止,最好的解决方案是在插入对象中的每个元素运行一个查询: collection.u

我只想在嵌入文档还没有密钥的情况下,将新值插入到嵌入文档中。例如,我的文档最初是

{
    name: "doc1",
    embeddedDoc: {
        a: 123,
        b: 456
    }
}
然后,如果我要“插入”
{b:789,c:101}
,我希望结果具有
嵌入的doc:{a:123,b:456,c:101}
(插入新的
c
,不要触摸现有的
b
)。有办法做到这一点吗

到目前为止,最好的解决方案是在插入对象中的每个元素运行一个查询:

collection.update(
    {"embeddedDoc.b": {$exists: false}},
    {$set: {"embeddedDoc.b": 456}}
)

我非常怀疑,对于许多属性,您是否可以进行比2次查询更好的查询。如果您有许多属性,您可以进行第一次查询以获取所有属性,然后了解您拥有的属性,将缺少的一个作为集合差异来查找。然后只更新丢失的属性


因此,对于任意数量的属性,您将得到两个查询和一个简单的应用程序逻辑。请注意,在高度繁忙的应用程序中,query1(查找)和query2(更新)之间可能会发生某些事情

就我个人而言,我的文档中没有对象,而是数组。它本身并不能解决不过度加载数据的问题,但它确实将“键”上的“查找”转换为使用可以索引的“数据”。如果你打算定期进行此类更新,这将产生“巨大”的影响

{
“名称”:“Doc1”,
“财产”:[
{“key”:“a”,“value”:123},
{“键”:“b”,“值”:456}
]
}
因此,对于“b”和“c”的新数据,您可以进行如下查询尝试:

db.collection.update(
{“properties.key”{“$nin”:[“b”,“c”]},
{ 
“$push”:{
“财产”:{
“$each”:[
{“键”:“b”,“值”:789},
{“键”:“c”,“值”:101}
]
}
}
},
{“多”:真}
)
如上所述,至少超过“可以”使用“键”查找无法使用的索引,并且您至少可以“尝试”将此操作作为“第一次尝试”来执行,如果文档确实满足给定条件,其中“b”和“c”都不存在,“键”值,则这些文档将受到影响

回退方案当然是对这里的每个属性分别进行尝试,但整个过程确实不难解决:

var obj={“b”:456,“c”:101};
变量键=对象键(obj),
mapped=keys.map(函数(键){
返回{“key”:key,“value”:obj[key]};
});
var bulk=initializeOrderedBulkop();
bulk.find({“properties.key”:{“$nin”:keys}).update({
“$push”:{“属性”:{“$each”:映射}
});
键。forEach(功能(键){
bulk.find({“properties.key”:{“$ne”:key}).update({
“$push”:{“属性”:{“键”:键,“值”:obj[key]}
});
});
bulk.execute();
注意,如果第一个查询确实成功,那么其他所有查询都可能是“无操作”。但是,如果您像这样使用“multi”进行测试,那么您永远无法真正确定,除非您已经知道要测试多少文档。因此,一次发送所有邮件可能是“安全总比抱歉好”

因此,它很好,代码简单,由于批量操作,只需往返服务器一次,并且由于能够使用索引,在查找数据以匹配条件方面“高效”


要实现的“丢弃合并”逻辑始终意味着多个更新。但是,如果你至少让这个过程尽可能“高效”,那么这至少就少了一件需要担心的事情。

谢谢。我在问题中忽略了可能要更新多个文档(通常是1到5个),因此必须对每个文档执行query1(查找)和query2(更新)。插入文档中的属性的典型数量是10到50,因此每个文档两个查询仍然获胜,尽管这需要更多的代码。由于其他原因,我不得不按照您的建议更改为键/值数组,并尝试了一下。我认为您的更新查询不起作用,因为在您的示例中,谓词
$nin:[“b”,“c”]
与具有键
[“a”,“b”]
的文档不匹配,
$push
如果匹配就会添加重复项。需要像
$addToSet
这样的东西,并带有一个可指定的键。@ZachB请仔细阅读,因为术语use there是“trust”,这意味着它只能在两者都不存在的情况下工作,如果不存在,则返回到其他操作。这实际上是关于批量操作,而不是保证第一次尝试将所有东西同时放入时都能正常工作。哦,我明白了。谢谢