2012-11-20 80 views
2

我有一個MongoDB的集合,如下所示:更新MongoDB記錄會重寫整個記錄還是僅更新字段?

comment_id (number) 
comment_title (text) 
score (number) 
time_score (number) 
final_score (number) 
created_time (timestamp) 

分數是和整數,這通常用$ INC 1或更新每當有人或票上下該記錄-1。 但time_score更新使用函數相對於時間戳和當前時間和其他因素,如多少(整天通過)和多少(整個星期過去).....等

所以我做$ inc和$直接對數據庫進行分析,但對於time_score,我從db中獲取數據,計算新分數並將其寫回。我擔心的是,如果許多用戶在計算time_score期間遞增「score」字段,那麼當我將time_score寫入db時,它將破壞最後一個score值。

要更清楚地更新Mongo記錄中的特定字段是否會重寫整個記錄或僅更新字段? (假設所有這些字段都被索引)。

回答

2

默認情況下,整個文檔被重寫。要指定更改的字段而不修改其他內容,請使用$set運算符。

編輯:該答案的評論是正確的 - 任何update modifiers將導致只有相關領域被重寫,而不是整個文件。通過「默認」,我的意思是沒有使用特殊修飾符的情況(提供了一個vanilla文檔)。

+1

這是不準確的 - 當您使用各種運算符(如$ inc)時,只會更改指定的字段。只有當您傳遞完整文檔以進行更新而沒有任何更新操作員時,整個文檔纔會被重寫。 –

+0

實際上,每一個更新操作符都只會修改它應用的字段。覆蓋整個文檔是例外而不是規則,因爲很少有人想要在現實世界中覆蓋整個文檔。 –

+0

你們中的任何人都可以發佈一個鏈接給我,以驗證這是如何完成更新! – Shashank

0

您所描述的算法絕對不是線程安全的。

當您閱讀整個文檔時,更改一個字段,然後回寫整個文檔,您正在創建競爭條件 - 文檔中的任何字段在讀取之後修改,但寫入之前將被您的更新覆蓋。

這是使用$ set或$ inc操作符自動設置單個字段而不是根據可能過時的值更新整個文檔的衆多原因之一。

另一個原因是設置/更新單個字段「in-place」比寫入整個文檔更有效率。另外,當傳遞較小的更新文檔({$ set:{field:value}},而不是文檔的整個新版本)時,您的網絡負載較低。

+0

不,你錯了,你沒有得到我的問題我不是說我會寫整個文件我說我不想這樣做,上面的答案是正確的。 – Shehabix

+1

您所描述的算法對於任何不執行原子更新的操作都不是線程安全的。 $ inc是安全的,但是基於可能過時的值的$ set是不安全的。 –

+0

如果價值是一個不是特定數字的計算,我該怎麼辦?我可以在mongo中做這樣的事情: $ set:{field:equation * field - another_field}? – Shehabix