我试图设置0项。通过id查询获取的文档数量。
db.warehouses.update(
// query
{
_id:ObjectId('5322f07e139cdd7e31178b78')
},
// update
{
$set:{"items.$.qty":0}
},
// options
{
"multi" : true, // update only one document
"upsert" : true // insert a new document, if no existing document match the query
}
);
返回:
如果没有包含数组的相应查询字段,则不能应用位置操作符。
这是我想设置所有项目的文档。数量为0
{
"_id": { "$oid" : "5322f07e139cdd7e31178b78" },
"items": [
{
"_id": { "$oid" : "531ed4cae604d3d30df8e2ca" },
"brand": "BJFE",
"color": "GDRNCCD",
"hand": 1,
"model": 0,
"price": 500,
"qty": 0,
"type": 0
},
{
"brand": "BJFE",
"color": "GDRNCCD",
"hand": 1,
"id": "23",
"model": 0,
"price": 500,
"qty": 4,
"type": 0
},
{
"brand": "BJFE",
"color": "GDRNCCD",
"hand": 1,
"id": "3344",
"model": 0,
"price": 500,
"qty": 6,
"type": 0
}
],
"name": "a"
}
EDIT
这个问题缺少的细节是需要更新的字段实际上在子文档中。这大大改变了答案:这是对可能更新数组元素所能做的事情的约束。这在文档中有清楚的解释。主要在这一段:
位置$操作符充当第一个与查询文档
匹配的元素的占位符。
是这样的。像这样在单个语句中尝试更新所有数组元素,将无法工作。要做到这一点,您必须执行以下操作。
db.warehouses.find({ "items.qty": { "$gt": 0 } }).forEach(function(doc) {
doc.items.forEach(function(item) {
item.qty = 0;
});
db.warehouses.update({ "_id": doc._id }, doc );
})
基本上是更新每个数组元素的方法。
.update()
中的multi设置表示跨多个"文档"。不能应用于数组的多个元素。因此,目前最好的选择是将整个系统替换掉。或者在这种情况下,我们也可以替换整个文档,因为我们无论如何都需要这样做。
db.eval(function() {
db.warehouses.find({ "items.qty": { "$gt": 0 } }).forEach(function(doc) {
doc.items.forEach(function(item) {
item.qty = 0;
});
db.warehouses.update({ "_id": doc._id }, doc );
});
})
在整个集合中更新所有元素并不简单。原来
几乎就是错误的意思。要使用位置操作符,首先需要匹配。如:
db.warehouses.update(
// query
{
_id:ObjectId('5322f07e139cdd7e31178b78'),
"items.qty": { "$gt": 0 }
},
// update
{
$set:{"items.$.qty":0}
},
// options
{
"multi" : true,
"upsert" : true
}
);
因此,如果match条件位于小于 0的项的位置,则将索引传递给位置操作符。 p。S:当muti为true表示它更新每个文档。如果您只表示一个,则保留false
。
只有在第一个参数中指定数组(即用于标识要更新的文档的查询部分)时才能使用$ positional操作符。
位置$操作符标识要更新的数组字段中的元素,而无需显式指定该元素在数组中的位置。