我有一个看起来像这样的Mongo系列:
{
"id": _id_,
"doc": _some data_,
"timestamp": _timestamp_
}
如果没有一个具有相同 id 的条目,我想插入一个新条目,如果存在,请更新现有条目,但是只有在新文档的时间戳大于现有条目。
在MongoDB中实现此目标的最佳方法是什么?我可以在一个查询中做到吗?
答案 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
)