我需要在MongoDB集合文档中的数组中添加一个对象,插入后我需要确保所有数组的元素都按其属性排序.
因为我需要数组中的对象是唯一的,所以我使用$addToSet而不是$push.这是我正在尝试的一个例子:
db.perros.update(
{name: "Risas"},
{
$addToSet: {propiedades: {name: "cola", cantidad: 1}},
$push: { propiedades: { $each: [ ], $sort: {cantidad: -1} }}
});
Run Code Online (Sandbox Code Playgroud)
但是,这将失败,出现以下Mongo错误:
WriteResult({
"nMatched" : 0,
"nUpserted" : 0,
"nModified" : 0,
"writeError" : {
"code" : 16837,
"errmsg" : "Cannot update 'propiedades' and 'propiedades' at the same time"
}
})
Run Code Online (Sandbox Code Playgroud)
当你考虑集合时这是显而易见的,但是$ push操作甚至不关心数组内部的内容......如何在不必使用的情况下实现这一点$push?
Bla*_*ven 11
通过正确识别您需要执行的操作,您就是其中的一部分.但当然$sort不是一个有效的修饰符,$addToSet因为MongoDB的口头禅是"集合不被认为是有序的":
$ addToSet不保证修改集中元素的特定排序.
此错误表明的另一个问题是,您不能同时在属性的同一路径上使用多个更新运算符(例如$addToSet和$push).实际上对于执行不同的更新运算符"没有顺序",所以它们不能保证在$addToSet之前发生$push.实际上它们可能并行运行,这就是错误和不允许的原因.
答案当然是"两个"更新声明.一个用于$addToSet和一个以应用$sort通过由"推动"空数组$each,
但由于我们真的不想"等待"每个更新完成,这就是"批量"操作API的用途.因此,您可以在一次发送中将两条指令发送到服务器并获得一个响应:
var bulk = db.perros.initializeOrderedBulkOp();
bulk.find({ "name": "Risas" }).update({
"$addToSet": {
"propiedades": { "name": "cola", "cantidad": 1 }
}
});
bulk.find({ "name": "Risas" }).update({
"$push": {
"propiedades": {
"$each": [ ], "$sort": { "cantidad": -1 }
}
}
});
bulk.execute();
Run Code Online (Sandbox Code Playgroud)
所以这仍然只是服务器的一个请求和一个响应.它仍然是"两个"操作,但是某些线程抓住upadte的临时状态的开销和可能性是可以忽略的.
这种方法有一种替代方法,即将"set detection"逻辑移动到.find()update语句的一部分,然后只应用于$push要添加到"set"的成员尚不存在的位置:
var bulk = db.perros.initializeOrderedBulkOp();
bulk.find({
"name": "Risas",
"propiedades": {
"$not": { "$elemMatch": { "name": "cola", "cantidad": 1 } }
}
}).update({
"$push": {
"propiedades": {
"$each": [{ "name": "cola", "cantidad": 1 }], "$sort": { "cantidad": -1 }
}
}
});
bulk.execute();
Run Code Online (Sandbox Code Playgroud)
当然复杂的是,如果你在这里添加"多个"数组元素,你需要在条件中包装那些$not和$elemMacth测试$and,然后如果这些元素中"只有一个"有效,那么它就不能单独添加.
您可以"首先"尝试"多个"项目的那种操作,但是您应该使用与上面相同的逻辑对每个单独的数组元素执行"后备"执行,以"测试""推"的可能性每一个.
因此$addToSet,使用多个数组条目可以轻松实现第二部分.对于一个条目,它只是"查询"非常简单,对于多个条目,$push可能是使用"第一"模式的较短路径$addToSet和$push使用空数组来"排序"结果,因为应用第二个模式意味着多个更新测试无论如何.
| 归档时间: |
|
| 查看次数: |
6266 次 |
| 最近记录: |