插入不存在元素的数组,否则更新它(具有多个条件)

时间:2017-10-18 09:11:51

标签: mongodb mongodb-query

{
 _id:'1',
name:'apple',
option:[{
weight:'10',
size:'40'
price:'40',
},
{weight:'40',
 size:'40'
price:'200'}]
}

如果重量或大小不同,我想在阵列中插入新对象,如果大小和重量都匹配,我想更新它。我该怎么办?

2 个答案:

答案 0 :(得分:1)

your previous question类似,您使用的是.bulkWrite(),但由于数组元素选择具有“多个条件”,因此您可以使用$elemMatch

db.collection.bulkWrite([
  { "updateOne": {
    "filter": { 
      "_id": "1", 
      "option": { 
        "$elemMatch": { weight": "40", "size": "40" }
      }
    },
    "update": { 
      "$set": { "option.$.price": "300" }
    }
  }},
  { "updateOne": {
    "filter": {
      "_id": "1",
      "option": {
        "$not": {
          "$elemMatch": { weight": "40", "size": "40" }
        }
      }
    },
    "update": {
      "$push": { "option": { "weight": "40", "size": "40",  "price": "300" } }
    }
  }},
  { "updateOne": {
    "filter": { "_id": 1 },
    "update": {
      "$setOnInsert": {
        "option": [
           { "weight": "40", "size": "40",  "price": "300" }
         ]
      }
    },
    "upsert": true
  }}
])

所以操作是:

  1. 测试$elemMatch中匹配条件的数组元素是否存在,然后$set匹配的值。

  2. 测试数组元素是否为$not否定。您可以在每个属性上使用$ne,但是否定两个匹配更清晰的条件。

    "$elemMatch": { "weight": { "$ne": "40" }, "size": { "$ne": "40" } }
    

    无论如何,当找到与提供的条件匹配的时,您$push新数组元素。

  3. 仅在未找到主文档_id的情况下尝试“upsert”,并使用$setOnInsert以便在找到文档时此操作不执行任何操作。

  4. 与之前相同,尽管将整个批次发送到服务器,但其中只有一个实际上会写入任何内容。

答案 1 :(得分:0)

您可以通过一个仅限mongodb的操作将所有内容连接在一起,通过添加一个'版本'可能会更好。字段和使用乐观锁定,像java + spring-data为你做(google for @Version)。这将允许在持久性之前对完整对象进行复杂的更改和验证。