以下是這種情況:我想用特定ID更新文檔,並且其update_time比較新的文檔更舊,如果找不到這樣的文檔,請使用較新的文檔創建一個文檔一。使用特定查詢更新的更好方法
第一個解決方案給我的是:
db.collection.update(
{
'_id': 'the_specific_id',
'update_time': {'$lt': new_date_time}
},
{
'$set' :{
'field_1': 'value_1',
'field_2': 'value_2',
'update_time': new_data_time
}
},
{ 'upsert': true}
)
在這個解決方案中,如果文檔被發現,然後更新是好的。如果由於找不到'_id'而找不到doc,upsert很好。但是,如果找不到doc,因爲db中的doc具有較新的'update_time',則後續upsert不正確(因爲主鍵重複)。
所以我有這個(psudo代碼)結束:
try:
db.collection.insert({
'_id': 'the_specific_id',
'field1': 'value1',
'field2': 'value2',
'update_time': new_date_time
})
except Exception as e:
if e.message.find('duplication'):
db.collection.update(
{
'_id': 'the_specific_id',
'update_time': {'$lt': new_date_time}
},
{
'$set' : {
'field_1': 'value_1',
'field_2': 'value_2',
'update_time': new_data_time
}
},
{ 'upsert': false})
這看起來太過複雜。我想知道這個解決方案是否有更好的方法?
有辦法,但如果你是「真」用'_id'場那麼它已經是「獨一無二」的,所以一個「upsert」**不會**發生,而您將會收到一個重複的鍵錯誤,並且不會有任何改變。其他解決方案基於相同的原理而有所不同,但是'_id'基本上覆蓋了它,並且在這種情況下,「upsert」是完全正確的,如前所述。在你的問題中'$ set'或其他更新操作符的缺失確實是比較麻煩的,因爲你實際上會在沒有它們的情況下「覆蓋」其他字段,如「update_time」數據。因此,每秒鐘的寫入都會嘗試在dup鍵上插入並失敗。 –
'$ set'操作員添加 –
我認爲更重要**事實**有**不可能重複主鍵**。由於日期不匹配,不會發生upsert。它的結果將永遠是一個重複的關鍵錯誤。這是你如何實現你想要的東西的本質。所以如果你在這裏講真相,那麼「upsert」已經起作用了。 –