我已經在LinkedIn上回答了這個問題,我認爲這是分享的有用和有趣的東西。這個問題是:MongoDB中的條件upsert
「假設我們有一個文件,如{_id: ..., data: ..., timestamp: ...}
有什麼辦法來寫的更新標準,這將滿足下列規則:
1如果沒有與以下_id
沒有文件然後插入該文件;
2如果存在文件與以下_id
然後
2.1如果新的時間戳大於存儲時間戳n更新data
;
2.2,否則什麼都不做」的
我已經在LinkedIn上回答了這個問題,我認爲這是分享的有用和有趣的東西。這個問題是:MongoDB中的條件upsert
「假設我們有一個文件,如{_id: ..., data: ..., timestamp: ...}
有什麼辦法來寫的更新標準,這將滿足下列規則:
1如果沒有與以下_id
沒有文件然後插入該文件;
2如果存在文件與以下_id
然後
2.1如果新的時間戳大於存儲時間戳n更新data
;
2.2,否則什麼都不做」的
解決方案應該做的伎倆,你只需要忽略DUP鍵錯誤的例子是在蒙戈外殼下式給出:
> var lastUpdateTime = ISODate("2013-09-10")
> var newUpdateTime = ISODate("2013-09-12")
>
> lastUpdateTime
ISODate("2013-09-10T00:00:00Z")
> newUpdateTime
ISODate("2013-09-12T00:00:00Z")
>
> var id = new ObjectId()
> id
ObjectId("52310502f3bf4823f81e7fc9")
>
> // collection is empty, first update will do insert:
> db.testcol.update(
... {"_id" : id, "ts" : { $lt : lastUpdateTime } },
... { $set: { ts: lastUpdateTime, data: 123 } },
... { upsert: true, multi: false }
...);
>
> db.testcol.find()
{ "_id" : ObjectId("52310502f3bf4823f81e7fc9"), "data" : 123, "ts" : ISODate("2013-09-10T00:00:00Z") }
>
> // try one more time to check that nothing happens (due to error):
> db.testcol.update(
... {"_id" : id, "ts" : { $lt : lastUpdateTime } },
... { $set: { ts: lastUpdateTime, data: 123 } },
... { upsert: true, multi: false }
...);
E11000 duplicate key error index: test.testcol.$_id_ dup key: { : ObjectId('52310502f3bf4823f81e7fc9') }
>
> var tooOldToUpdate = ISODate("2013-09-09")
>
> // update does not happen because query condition does not match
> // and mongo tries to insert with the same id (and fails with dup again):
> db.testcol.update(
... {"_id" : id, "ts" : { $lt : tooOldToUpdate } },
... { $set: { ts: tooOldToUpdate, data: 999 } },
... { upsert: true, multi: false }
...);
E11000 duplicate key error index: test.testcol.$_id_ dup key: { : ObjectId('52310502f3bf4823f81e7fc9') }
>
> // now query cond actually matches, so update rather than insert happens which works
> // as expected:
> db.testcol.update(
... {"_id" : id, "ts" : { $lt : newUpdateTime } },
... { $set: { ts: newUpdateTime, data: 999 } },
... { upsert: true, multi: false }
...);
>
> // check that everything worked:
> db.testcol.find()
{ "_id" : ObjectId("52310502f3bf4823f81e7fc9"), "data" : 999, "ts" : ISODate("2013-09-12T00:00:00Z") }
>
唯一惱人的部分是那些錯誤,但它們便宜且安全
db.collection.update({
_id: ObjectId("<id>"))
},
{timestamp: <newTimestamp>, data: <data>},
{upsert: true})
此操作將更新現有文檔,如果它符合存在條件並且現有時間戳較少比newTimestamp;否則會插入一個新的文件。
這將是一個更好的例子,如果你解釋它爲什麼工作 –
它不起作用 - 使用更新操作符和僅使用字段值僅有一個區別:http://docs.mongodb.org/manual/reference/method /db.collection.update/#update-parameter。 –
@AlekseyIzmailov我同意有一個區別,但是,在這種情況下,文檔完全由三個字段定義:_id,時間戳和數據。這工作。 – Rishi