我需要向 MongoDB 集合文档中的数组添加一个对象,在插入它之后我需要确保所有数组的元素都按其属性之一排序。
因为我需要数组中的对象是唯一的,所以我使用 $addToSet
而不是 $push
。这是我正在尝试的示例:
db.perros.update(
{name: "Risas"},
{
$addToSet: {propiedades: {name: "cola", cantidad: 1}},
$push: { propiedades: { $each: [ ], $sort: {cantidad: -1} }}
});
然而,这将失败并出现以下 Mongo 错误:
WriteResult({
"nMatched" : 0,
"nUpserted" : 0,
"nModified" : 0,
"writeError" : {
"code" : 16837,
"errmsg" : "Cannot update 'propiedades' and 'propiedades' at the same time"
}
})
当你考虑 sets 时,这是显而易见的,但是 $push 操作甚至不关心数组内部的内容......如何在不使用 $push< 的情况下实现这一点
?
最佳答案
通过正确识别您需要执行的操作,您已经完成了部分工作。但当然$sort
不是 $addToSet
的有效修饰符因为 MongoDB 的格言是“集合不被认为是有序的”:
$addToSet does not guarantee a particular ordering of elements in the modified set.
此处错误指示的另一个问题是您不能在同一属性的同一路径上同时使用多个更新运算符(例如 $addToSet
和 $push
)。实际上,不同更新操作符的执行“没有顺序”,因此它们不能保证 $addToSet
发生在 $push
之前。事实上,它们很可能是并行执行的,这就是错误的原因,并且这是不允许的。
答案当然是“两个”更新语句。一个用于$addToSet
,一个用于通过$each
“推送”一个空数组来应用$sort
。 ,
但由于我们真的不想“等待”每次更新完成,这就是“批量”操作 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();
所以这实际上仍然只是对服务器的一次请求和一次响应。它仍然是“两个”操作,但是某些线程获取更新的临时状态的开销和可能性可以忽略不计。
这种方法还有一个替代方法,就是将“设置检测”逻辑移动到更新语句的 .find()
部分,然后只应用 $push
要添加到“集合”的成员尚不存在:
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();
当然,复杂的是,如果您要在此处添加“多个”数组元素,则需要将这些 $not
包裹起来和 $elemMacth
在 $and
中进行测试条件,然后如果这些元素中“只有一个”有效,则不能单独添加它。
您可以“首先”使用“多个”项目“尝试”这种操作,但是您应该使用与上述相同的逻辑对每个单独的数组元素进行“回退”执行“测试”每个人“插入”的可能性。
因此 $addToSet
使用多个数组条目使第二部分变得容易。对于一个条目,只需“查询”和 $push
就非常简单,对于多个条目,使用带有 $addToSet
的“第一个”模式可能是更短的路径$push
一个空数组来“排序”结果,因为应用第二个模式意味着无论如何都要进行多次更新测试。
关于arrays - 如何使用 MongoDB 将对象 $addToSet 设置为数组并 $sort ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31351572/