關於作者
Eric KK
曾供職於雲盾、簡書,資深前端工程師,we-plugin開源項目組成員,現任潮辦科技CTO,基於騰訊雲開發轉型全棧開發者,獨立完成多個微信小程序從0到1全功能完整上線運行。
「使用雲開發之後,一個小程序可以快速的從無到有上線運行,這個速度是傳統開發不能比的,特別適合初創團隊快速上線產品搶佔市場或試錯。而使用雲開發,我們通常要做的第一件事就是設計資料庫,雲開發的資料庫使用結構化的文檔來存儲數據,不再是關係型資料庫裡每個行列交匯處都必須有且只有一個值,它可以是一個數組、一個對象,或者更加複雜的嵌套。
在初期產品需要快速出可用原型,上線時間緊迫的情況下,資料庫設計難免會有欠考慮的地方,等產品開始進入迭代器就可能會有重構需求。團隊最近對項目進行了重構,寫一篇文章分享我們在做重構的一些心得。」
目的
這次資料庫重構只有一個目的,把一個最初內嵌的欄位提取出來,單獨創建一個集合來管理。也就是把反範式化設計的資料庫結構轉成範式化的設計。
關於範式化和反範式化,你可以看雲開發布道師東哥的文章:
https://club.cloudbase.net/handbook/tcb/1203.html
舊數據方案的痛點
在產品上線的第一個版本時,bagList欄位是內嵌在一個user文檔裡的,如下:
這裡的數據是精簡版,真實情況還會有很多商品信息、用戶信息等,此處只是舉例說明。
這樣的反範式化設計在最初上線的版本中並沒有什麼問題,因為商品價格較高,早期也認為用戶並不會大量購買。然而沒想到的是,在經過一波運營宣傳後,用戶量開始猛增,其中也出現了一些土豪用戶,他們的購買數量已經不是個位數了,有的都超過了100件以上,此時bagList欄位的數組長度就變得非常大。
在這個時候,數據分頁、商品發貨、修改商品信息就已經很難維護,一直使用了層層的聚合操作先查詢出來,然後再修改。猶豫不決之際,新的開發需求出現,要求可以讓用戶之前互換數據,原有的數據結構想要實現類似的功能存在較高的實現成本。因此,決定乾脆重構資料庫,提升開發效率。
重構步驟
將 bagList欄位單獨拿出來形成一個集合的好處有很多,數據分頁很方便,修改商品信息很簡單,且很多雲資料庫的原子操作修改都可以直接使用,更重要的是新需求互換功能只需要修改對應商品的所有者 userid 就可以完成。但此時內嵌結構已經使用了很久,數據也已經記錄了很多,如何把這些歷史數據無縫銜接的拿出來成了問題,這裡使用了一系列的聚合操作來完成。
這裡用的是雲開發管理控制臺自帶的高級操作腳本,首先第一步開啟聚合模式,在聚合中單次limit最大數現為10000,因改版時用戶數正好低於10000,所以這裡直接拉到最大。然後使用match來刪選user集合中bagList欄位不為空數組的文檔。緊接著使用project選定在下一階段想要的展示的欄位,_id欄位默認存在,其餘欄位直接捨棄。此時的執行結果如下圖:
接下來我們就需要用unwind來拆分bagList,拆分完的數據結構如下:
此時每一個商品已經單獨抽離出來,如果此時的結構已經達到了想要的要求,那就可以直接使用現有數據,如果還想自定義一下,那就可以繼續使用聚合操作來完成,如上面我因為還有其他需求,使用聚合再次改變了一些結構寫法,聚合的操作可以去雲開發文檔聚合學習。
不過,聚合出來的數據並不是嚴格的json數據,雖然現在的雲開發控制臺的高級腳本可以批量添加數據,add方法中的data可以為數組,這在數據量小的情況下可以直接使用,但我們這次聚合出來幾千條數據,經測試,雲開發的高級腳本並不支持那麼大的數據量一次性導入,那麼我們可以使用資料庫的json格式導入。
創建一個新集合products,這裡使用vscode把我們聚合出來的數據複製粘貼到一個名為products.json的新文件中(名稱隨意),然後將最外層的[]包裹刪除,全局搜索 },換行{ 替換為 }換行{ ,把每條數據之間的逗號去除(注意:在搜索的時候,換行也要,不然內嵌數據的逗號也會被替換),保存並使用 json方式把數據導入到products集合就大功告成啦。
總結
在開發的過程中,難免會遇到需要重構資料庫的場景,我自己沒有搜索到相關的文檔,便將自己的實踐經驗分享出來,做第一個吃螃蟹的人,供大家參考。
如果你對重構方面有任何問題和想法,歡迎留言和一起討論。