天天看點

寫給MongoDB開發者的50條建議Tip10

本系列文章翻譯自《50 Tips and Tricks for MongoDB Developers》,暫時沒有找到中文版,反正自己最近也在深入學習mongodb,是以正好拿來翻譯一下。一方面加強自己學習的效果,另一方面讓大 家也一起來體驗一下需要我們這些mongodb使用者需要注意的地方。

首先聲明自己的英文水準不是太高,加之有些英文翻譯成中文也找不到合适的詞來表達,是以在文章中可能會出現英文原詞,或者說有些地方的翻譯會有些生 硬,也就是說會出現直譯的地方。翻譯該書的主要目的是為大家學習探讨用的,如果有翻譯不精準的地方,或者說有更加精準的翻譯,還請大家指出,我會及時的更 正的,在此先謝過各位了。

Tip10.Design documents to be self-sufficient

将文檔設計成自給自足的

mongodb應該是一個大的,無聲的資料存儲容器。它本身不做任何處理,隻是負責存儲和讀取資料。你應該堅持這個目的,避免強迫mongodb進行一些用戶端可以進行的計算工作。甚至是一些例如計算平均數或者是計算加和這樣瑣碎的工作,都應該推給用戶端去做。

如果你非要進行一些需要計算的查詢,你有兩個選擇:

招來嚴重的性能懲罰。在mongodb中使用javascript進行計算。

在文檔中顯式的存儲這些資訊。

通常來說,你應該在文檔中顯式的存儲這些資訊。

假設你需要查詢apple和orange總共是30個的文檔。

  "_id":123, 

  "apple":10, 

  "orange":12 

如果文檔是上面的格式,就需要在查詢的同時使用javascript進行計算工作,非常低效。相反,在文檔中加一個total的字段。

  "apple":12, 

  "orange":14, 

  "total":30 

在更新apple和orange數量的時候,同時更新一下total的資訊。

>db.food.update({"_id":123},{"$inc":{"apple":10,"orange":-2,"total":8}}) 

>db.food.findOne() 

  "apple":22, 

  "orange":12, 

  "orange":38 

假設是下面的情形,你的total存儲的是水果的類型數量。

  "apple":10. 

  "orange":24, 

  "total":2 

現在,你需要更新文檔,但是有可能增加字段,也有可能不增加字段。那你是否增加total的值呢?如果更新語句是下面的情況,你就需要更新total的值。

>db.food.update({"_id":123},{"$inc":{"banana":12,"total":1}}) 

相反的,如果banana字段已經存在了呢,我們就不應該增加total字段的值。但是在用戶端,我們不知道這些情況。

通常在這種情況下,我們有兩種處理方法:速度快,會産生不一緻;速度慢,沒有不一緻。

快速的辦法就是不管三七二十一,給total加1,同時讓應用意識到将來還需要檢查total的值是否正确。可以運作一個不間斷的批量處理任務,修正這些資料。

如果應用可以接受額外的處理時間,我們可以使用findAndModify方法,将文檔lock(設定一個locked字段,其他的寫請求會檢查這個字段),傳回文檔,然後在正确更新total的值之後,将lock字段設定為false。

>var resule=db.runCommand({"findAndModify":"food", 

  "query":{"_id":123,"locked":false}, 

  "update":{"$set":{"locked":true}}}) 

>if ("banana" in result.value){ 

  db.food.update({criteria,{"$set":{"locked":false}."$inc":{"banana":20}}}) 

  }else{ 

  db.food.update({criteria,{"$set":{"locked":false},"$inc":{"banana":3,"total":1}}}) 

本文轉自 virusswb 51CTO部落格,原文連結:http://blog.51cto.com/virusswb/798386,如需轉載請自行聯系原作者

繼續閱讀