2012-05-20 53 views
18

文件考慮一個簡單蒙戈文件結構僅設置值:mongodb的:upserting:如果被插入

{_id,firstTime,lastTime}

客戶端需要插入一個文檔具有已知ID,或更新現有文檔。 'lasttime'應該總是設置爲最近的一段時間。對於'firstTime',如果正在插入文檔,則應將'firstTime'設置爲當前時間。但是,如果文檔已經創建,那麼'firstTime'保持不變。我想純粹用upserts來做(避免查找)。

我抓取http://www.mongodb.org/display/DOCS/Updating,但我只是不明白如何完成特定的操作。

我不認爲這是不合理的,有$ push和$ addToSet操作可以在數組字段上有效地做到這一點,只是在簡單字段上不會這樣做。這就像應該有像$ setIf操作。

+0

*如果文檔已經創建,該字段應該保持不變*不會調用upsert(如在您的標題中) –

+0

@ om-nom-nom我概述了最簡單的情況,我更新了描述,所以有一個總是被更新的字段。 –

+1

看起來像這個功能是針對2.4:https://jira.mongodb.org/browse/SERVER-340 – JohnnyHK

回答

27

我遇到了相同問題,並有用於然而< 2.4 2.4以來的$ setOnInsert運營商沒有簡單的解決方案讓你做到這一點。

db.collection.update(<query>, 
         { $setOnInsert: { "firstTime": <TIMESTAMP> } }, 
         { upsert: true } 
        ) 

查看2.4 release notes of setOnInsert瞭解更多信息。

1

沒有辦法只用一個upsert來做到這一點。您必須將其作爲2個操作來執行 - 首先嚐試插入文檔,如果它已經存在,則由於_id索引上重複的鍵違例,插入將失敗。然後,您執行更新操作以將lastTime設置爲現在。

+0

恕我直言,這將失敗的目的,在做,等待,第一次操作相當於同步查找。我沒有看到「嘗試失敗」並找到並更新的區別...... –

+1

有多個併發作者的查找和更新和更新方法存在爭用條件。如果另一個編寫者在第一個線程執行讀取操作和執行寫入操作之間創建/更改文檔,則可以結束重寫另一個線程執行的寫入操作。 – stbrody

+0

這就是爲什麼我需要它在單個write()操作中,所以要求Mongo以原子方式執行它。 –

1

試圖UPSERT基於現有內容文檔時,我遇到了一個非常類似的問題 - 也許這個解決方案會爲你工作也:

嘗試從你的記錄刪除了_id屬性,只有在查詢中使用它您更新的部分(你要翻譯從pymongo說話......)

myid = doc.get('_id') 
del doc['_id'] 
mycollection.update({'_id':myid}, {'$set':doc}, upsert=True)