pushOrModify like mongo子文档的运算符

时间:2016-04-07 03:41:24

标签: mongodb mongodb-query

我要做的是,如果存在subdoc,则更新它,否则,只用一种方法推送新的subdoc。

首先,找到30,然后找到

如果Town collection { name: "SweetTown", residents: [{ name: "Bob", reputation: 20 }] } 存在,我想将其声誉更改为{ name: "SweetTown", residents: [{ name: "Bob", reputation: 30 }] }

{ name: "Bob", reputation: 30 }

应该是

residents

或者不,将Town collection { name: "SweetTown", residents: [{ name: "Alice", reputation: 140 }] } 推送到{ name: "SweetTown", residents: [ { name: "Alice", reputation: 140 }, { name: "Bob", reputation: 30 } ]}

$addToSet

应该是

$push

我已经对此进行了大量搜索,并找到了一些方法,例如$neupsertuint16_tfileCh1 <<((uint16_t *) frame->extended_data[ch])[nb]<<"\n"; 选项。

但是,我无法正确地混合这些来解决这个问题。我怎样才能使它发挥作用?

1 个答案:

答案 0 :(得分:1)

这实际上需要&#34;两个&#34; (或&#34;三和#34;有upsert)更新语句,这是为什么&#34; Bulk&#34;操作存在。

db.collection.bulkWrite([
  // Attempt to update the matched element
  { "updateOne": {
    "filter": { 
      "name": "SweetTown",
      "residents.name": "Bob"
    },
    "update": {
      "$set": { "residents.$.reputation": 30 }    
    }
  },
  // $push the element where not matched
  { "updateOne": {
    "filter": {
      "name": "SweetTown",
      "residents.name": { "$ne": "Bob" } 
    },
    "update": { 
      "$push": { 
        "residents": { "name": "Bob", "reputation": 30 } 
      }
    } 
  }}
])

或者,如果你真的想要为"upsert"的基本文件添加"SweetTown",那么你需要将这个问题分开到它自己的测试中:

db.collection.bulkWrite([
  // Attempt to update the matched element
  { "updateOne": {
    "filter": { 
      "name": "SweetTown",
      "residents.name": "Bob"
    },
    "update": {
      "$set": { "residents.$.reputation": 30 }    
    }
  },
  // $push the element where not matched
  { "updateOne": {
    "filter": {
      "name": "SweetTown",
      "residents.name": { "$ne": "Bob" } 
    },
    "update": { 
      "$push": { 
        "residents": { "name": "Bob", "reputation": 30 } 
      }
    } 
  }},
  // Only use $setOnInsert when actually an upsert
  { "updateOne": {
      "filter": {
        "name": "SweetTown"
      },
      "update": {
        "$setOnInsert": {
           "residents": [{ "name": "Bob", "reputation": 30 }]
        }
      },
      "upsert": true
  }}
])

因此,当"upsert"实际发生时,的一般概念应用$setOnInsert操作。为了确保在这种情况下只发生这种情况,实际查看数组元素的其他操作不会使用"upsert"选项进行标记。那部分是故意的。

无论你怎么看待它,这些操作的一个只能在数据库中实际进行任何修改,因为要么找到元素,要么甚至文件都是找不到并创建了新的。

在任何情况下都不可能在单个更新语句中执行此类操作。然而,因为&#34; Bulk&#34;操作实际上只有一个请求一个响应,然后就您的应用程序而言,它只需要与服务器一次进行通信让服务器尝试所有这三件事并返回响应。

对于早期使用直接批量API,则替代语法为:

var bulk = db.collection.initializeOrderedBulkOp();

// $set matched where existing
bulk.find({ "name": "SweetTown", "residents.name": "Bob" }).updateOne({
  "$set": { "residents.$.reputation": 30 }
});

// $push where not existing
bulk.find({ "name": "SweetTown", "residents.name": { "$ne": "Bob" } }).updateOne({
  "$push": { "residents": { "name": "Bob", "reputation": 30 } }
});

// Attempt to upsert only
bulk.find({ "name": "SweetTown" }).upsert().updateOne({
  "$setOnInsert": {
    "residents": [{ "name": "Bob", "reputation": 30 }]
  }
})

bulk.execute();