2013-01-12 32 views
20

我使用mongodb + node.js + mongoose.js ORM後端。如何處理生產中的mongodb「模式」更改

咱們說II對象有一些嵌套數組沒有_id場

mongoose.Schema({ 
    nested: [{ 
    _id: false, prop: 'string' 
    }] 
}) 

然後,我想廣告_id領域的所有嵌套objectds,所以貓鼬的模式將是

mongoose.Schema({ 
    nested: [{ 
    prop: 'string' 
    }] 
}) 

然後我應該運行一些腳本來修改生產數據庫,對吧?處理這種變化的最佳方式是什麼?哪個工具(或方法)最適合用來實現這個改變?

+0

從你給出的例子看來,你想刪除_id而不是添加它。如果你想添加一個_id,你怎麼確定每個_id應該是什麼? – Eduardo

+0

我不明白你的意思。 _id:false告訴mongoose不要爲schema描述的對象生成_id,如果我從模式描述中刪除_id:false描述mongoose將生成帶有生成的_id的新文檔。我問的是正確的方式來填充所有現有的對象(沒有_id)與新的_ids。 – WHITECOLOR

+0

應該由系統生成_ids還是由您生成? – Eduardo

回答

12

無模式數據庫的一個顯着優點是您不必使用新模式佈局來更新整個數據庫。如果數據庫中的某些文檔沒有特定的信息,那麼您的代碼可以做適當的事情,或者選擇現在對該記錄做任何事情。

另一種選擇是懶洋洋地更新文件的要求 - 只有當他們看了一次。在這種情況下,您可能會選擇每個記錄/文檔版本標誌 - 最初甚至可能不會出現(並因此表示「版本0」)。即使這是可選的。相反,您的數據庫訪問代碼會查找它需要的數據,如果它不存在,因爲它是新的信息,在代碼更新後添加,那麼它會盡其所能地填充結果。

對於你的榜樣,轉換的_id:false成標準MongoId場,當代碼讀取(或更新後寫回),並且_id:false當前設置,然後進行更改,寫它,只有當它是絕對需要。

+0

對不起,我不明白'_id:false'是什麼意思。我真的很感興趣。你能解釋一下嗎? – hgoebl

+0

啊,我還沒看過問題文字,對不起,這不是你的錯。但是'_id:false'的例子可能會讓整個問題有點誤導。如果有一個更好理解所有人的例子,特別是那些不使用Mongoose的人,這將是很好的。 – hgoebl

+1

這將如何與操作像添加一個新的索引: 'patientSchema.index({patientId:1,institute:1},{unique:true})',在dev我不得不刪除舊的索引{獨特:true}'讓它工作 –

10

您確實必須編寫將覆蓋集合併爲每個文檔添加新字段的腳本。但是,確切的方式取決於數據庫的大小和存儲系統的性能。在文檔中添加一個字段會改變其大小,因此在大多數情況下會導致重定位。此操作對IO有影響,並受其限制。如果你的集合只有幾千個文檔,可能高達十萬個,那麼你可能只是在一個循環中迭代它,因爲整個集合可能適合內存,所有IO將在後面發生。但是,如果收集範圍遠遠超出可用內存,則該方法更復雜。我們通常遵循在生產中使用MongoDB中的下一個步驟:

  • 打開遊標與超時=假
  • 閱讀的文件塊到內存
  • 運行更新查詢對這些文件
  • 休眠一段時間避免過載IO子系統和損害生產中的應用
  • 重複,直到完成
  • 關閉遊標:)

文檔大小和睡眠時間必須通過實驗確定。通常,您希望在遷移期間避免使用mongostats中的QR/QW。對於速度較慢的驅動器(如Amazon上的EBS)上的較大集合,此IO安全方法可能需要數小時至數天。

+0

您是否有光標的簡短代碼示例?我特別感興趣的JavaScript版本,因爲我認爲這不是微不足道的,特別是睡了一段時間,並沒有得到並行... – hgoebl

+0

我沒有JavaScript的例子,但在PyMongo驅動程序禁用超時遊標只是通過傳遞timeout = False來查找()方法。我認爲JavaScript驅動程序會有這樣的東西。 –