仅当文档比MongoDB中的新文档旧时,我才可以升级?

时间:2020-05-12 13:29:45

标签: mongodb mongodb-query aggregation-framework

我有一个看起来像这样的Mongo系列:

{
  "id": _id_,
  "doc": _some data_,
  "timestamp": _timestamp_
}

如果没有一个具有相同 id 的条目,我想插入一个新条目,如果存在,请更新现有条目,但是只有在新文档的时间戳大于现有条目。

在MongoDB中实现此目标的最佳方法是什么?我可以在一个查询中做到吗?

3 个答案:

答案 0 :(得分:1)

FAIK,您无法在一个查询中执行此操作。您必须将各个查询分开,例如

db.collection.findOne()来查找记录。

const res = db.collection.findOne({_id: '5ebbc1ffe41253f2f8b336cf'});

如果记录不存在,请使用db.collection.insertOne()

if (!res) {
  db.collection.insertOne({
    _id: '5ebbc1ffe41253f2f8b336cf',
    doc: '_some_data_',
    timestamp: '_timestamp_'
  });
}

如果文档已经存在

else {
  db.collection.updateOne(
    {
      _id: '5ebbc1ffe41253f2f8b336cf',
      timestamp: {$lt: _timestamp_}
    },
    {
      $set: {_some_data_}
    }
  )
}

答案 1 :(得分:1)

只有在MongoDB版本> = 4.2时,您才可以在一个数据库事务中而不是多个事务中进行操作。原因来自版本4.2或更高版本的MongoDB .update()会在查询的更新部分接受聚合管道,这有助于在一个数据库调用中实现这一目标。

查询:

/** In the below query aggregation operator `$cond` helps to decide which value has to be set to respective fields &
 * will insert a new doc if `id` is not found in collection */
db.getCollection('collectionName').updateOne({"id" : inputId},
[
{$set : {doc : {$cond : [{$gt : [inputDateInDateFormat, '$timestamp']}, inputValueForDocField, '$doc']}}},
{$set : {timestamp : {$cond : [{$gt : [inputDateInDateFormat, '$timestamp']}, inputDateInDateFormat , '$timestamp']}}}
], {upsert : true})

注意:理想情况下,此查询应该有效,但是如果您使用的是旧版的Shell或任何旧版的mongo客户端(robo3T),则在这种情况下可能会失败,请尝试使用{ {1}}而非.update()-只是根据我以前的经验说。

答案 2 :(得分:-1)

new_entry = {
               "id": some_id,
               "doc": some_data,
               "timestamp": some_timestamp
            }


 collection.update_one(
                {
                 'id': {$eq: new_entry['id']}, 
                 'timestamp': {$lte: new_entry['timestamp']}
                },
                {'$set': new_entry},
                upsert=True
           )