MongoDB - 更新一个或另一个字段

MongoDB - Update One Field or Another

我对 MongoDB 很陌生,所以这可能是我对它的经验不足。我正在尝试做一个 upsert,当找到记录时,它将根据多个条件更新多个字段。

我在 collection 中有以下记录:

{
  modelId: "5e68c7eaa0887971ea6ef54c",
  versionId: 999,
  timeStamp: "1/1/2020",
  oldValue: 'Blue',
  newValue: 'Red'
}

我正在尝试使用单个 upsert 语句来满足以下条件,以避免多次访问数据库(基于匹配 modelId 和 [ 的文档的查询=17=] 找到:

  1. 如果 timeStamp 的新记录在 (lt) 现有文档之前,则更新 oldValue
  2. 如果 timeStamp 的新记录在 (gt) 现有文档之后,则更新 newValue
  3. 如果找不到匹配的记录,则插入新记录。

在伪代码术语中,我试图用 upsert 语句来做到这一点:

existingRecord = item in collection matching modelId and versionId

if(existingRecord = null)
{
   //insert newRecord
}
if(newRecord.timeStamp < existingRecord.timeStamp)
{
   existingRecord.oldValue = newRecord.oldValue
   existingRecord.timeStamp = newRecord.timeStamp
}
else if(newRecord.timeStamp > existingRecord.timeStamp)
{
   existingRecord.newValue = newRecord.newValue
   existingRecord.timeStamp = newRecord.timeStamp
}

我看到了根据日期条件进行 upsert 的可能性,例如:

db.collection.update( { id:o.id, date: { $lt:o.date } }, {$set : { o }}, {upsert:true} );

我不知道如何扩展它以便能够根据 timeStamp 值更新 oldValuenewValue

我计划每天将大量记录插入 collection,估计大约 1MM,我不想做一个 find() 然后一个 update() 每条记录。

我正在使用 Mongo 4.0,如有任何建议,我将不胜感激。

谢谢!

嗯,在4.0 版 中,您不能在更新查询中使用条件。因此,您最终会触发两个查询。

db.collection.update({condition}, { $set: { o } }, { multi: true ,upsert:true });
db.collection.update({!condition}, { $set: { n } }, { multi: true ,upsert:true });

但是,在版本 4.2 中,添加了 db.collection.update 管道,其中允许聚合。

而且,它只包含以下聚合阶段:

$addFields and its alias $set
$project and its alias $unset
$replaceRoot and its alias $replaceWith.

希望这会有所帮助:)

更新

我添加了 $set 阶段来更新文档。如果时间戳条件为真,它将更新,否则它不会更新。并适用于其他条件。

我已经使用了时间戳的长值,你可以根据你的情况使用。

db.collection.update(
  {
    modelId: "5e68c7eaa0887971ea6ef54c",
    versionId: 999,
  },
  [
    {
      $set:{
        "oldValue":{
          $cond:[
            {
              $lt:[
                "timestamp",
                1598598257000
              ]
            },
            "green",
            "$oldValue"
          ]
        }
      }
    },
    {
      $set:{
        "newValue":{
          $cond:[
            {
              $gt:[
                "timestamp",
                1518598257000
              ]
            },
            "pink",
            "$newValue"
          ]
        }
      }
    }
  ]
)