MongoDB更新了数组错误的所有字段

时间:2014-03-14 12:44:29

标签: mongodb mongodb-query

设置为0,通过id查询获取文档的items.qty。

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 
    }
);

返回:

如果没有包含数组的相应查询字段,则无法应用位置运算符。

这是我想将所有items.qty设置为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"
}

2 个答案:

答案 0 :(得分:4)

修改

问题中缺少的细节是要更新的必填字段实际上是在子文档中。这大大改变了答案:


这是对可能更新数组元素的约束。 documentation清楚地解释了这一点。主要在本段中:

  

位置$运算符充当与查询文档匹配的第一个元素的占位符

所以这就是事情。尝试在像这样的单个语句中更新所有数组元素工作。为此,您必须执行以下操作。

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()中的设置表示多个"文档"。 不能应用于数组的多个元素。所以目前最好的选择是取代整个事物。或者在这种情况下,我们也可以替换整个文档,因为无论如何我们都需要这样做。

对于真实批量数据,请使用db.eval()。但请先阅读文档:

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  
    }
);

因此匹配条件会在小于 0的项目中位置,然后索引被传递给位置操作员。

P.S :当 muti true 时,表示它会更新每个文档。如果你只是指一个,请保留false。这是默认值。

答案 1 :(得分:2)

只有在第一个参数中指定数组时才能使用$ positional operator(即,用于标识要更新的文档的查询部分)。

  

位置$运算符标识要更新的数组字段中的元素,而不显式指定元素在数组中的位置。