茫茫網海中的冷日 - 對這文章發表回應
茫茫網海中的冷日
         
茫茫網海中的冷日
發生過的事,不可能遺忘,只是想不起來而已!
 恭喜您是本站第 1672329 位訪客!  登入  | 註冊
主選單

Google 自訂搜尋

Goole 廣告

隨機相片
IMG_60D_00087.jpg

授權條款

使用者登入
使用者名稱:

密碼:


忘了密碼?

現在就註冊!

對這文章發表回應

發表限制: 非會員 可以發表

發表者: 冷日 發表時間: 2021/9/27 2:28:44

關於組織樹狀圖的資料結構設計方法

最近公司有一個需求:就是我們需要建立一個具有組織樹狀圖的平台。

玩家可以將此平台介紹給親朋好友或其他人來辦帳號。

而利用此連結註冊的新帳號會紀錄其介紹人,也就是所謂的「上線」,而相對於這個「上線」來說,自己就是「下線」。

「上線」在這個平台中可以查看到自己的所有「下線」與其所有「下線」的活動狀態,就像一棵樹狀結構一樣。

以上圖為例,2, 3, … 14 都可以算是 1 的 「下線」,而其中 2, 3 也是 1 的「直屬下線」。

做完了名詞解釋後,我們來談談這次的需求。

我們除了要能夠將此玩家的組織圖完整顯現,我們還要能夠計算出各個上下線之間的交易金額與歷史紀錄。

先撇除交易金額這些事務性的功能不看,由於每個玩家皆可以擁有自己的「下線」而且每個玩家的直屬下線個數也 不限制,因此這並非典型的二元樹(binary tree)。

某玩家可能有 m 個「直屬下線」,每個「直屬下線」也可以有各自的 n 個「直屬下線」,以此反覆…且沒有最大層數的限制。

基於以上規則,我們要如何在資料庫中儲存資料格式才能很好地在有限的Query次數中得知某玩家的「所有下線」呢?

若是我們只是在每個玩家的資料欄位中紀錄此玩家屬於哪個上線,貌似無法解決此問題。我們無法在有限次數的 Query 中得到所有下線的資料。

為了解決這個問題,我們有兩個方法,但是其實都是相同的概念。

  • 我們可以新增一個欄位,叫做 parents 這個欄位是一個 array 結構,當新玩家建立時,除了 記錄自己的上線之外,還 將自己的上線與其所有上線紀錄在此欄位之中。

以上方的 Tree 為例:我們可以將資料紀錄成類似如下的格式


{ id: 1,  parent: null, parents: [] },
{ id: 2, parent: 1, parents: [1, ] },
{ id: 3, parent: 1, parents: [1, ] },
{ id: 4, parent: 2, parents: [1, 2] },
{ id: 5, parent: 2, parents: [1, 2] },
{ id: 6, parent: 3, parents: [1, 3] },
{ id: 7, parent: 3, parents: [1, 3] },
{ id: 8, parent: 4, parents: [1, 2, 4] },
{ id: 9, parent: 4, parents: [1, 2, 4] },
{ id: 10, parent: 5, parents: [1, 2, 5] },
{ id: 11, parent: 5, parents: [1, 2, 5] },
{ id: 13, parent: 6, parents: [1, 3, 6] },
{ id: 14, parent: 7, parents: [1, 3, 7] },
...

未來當我們要找尋某玩家的所有下線時,只要 找尋 Database 中 parents 欄位有此玩家資訊的玩家,就可以在一次的 Query 中得到我們想要的結果了。

例如我們要找尋 2 的所有下線,我們只要找尋 parents 中有 2 的資料,即為結果: 4, 5, 8, 9, 10, 11

  • 我們新增一個欄位,叫做 path 這個欄位是一個 string。這個概念其實與上方非常相似,但是我們使用了 類似檔案路徑的結構來儲存相對關係。

一樣以上方的樹狀圖為例,若為此資料儲存方式,則資料的儲存長相可能如下:

{ id: 1,  parent: null, path: "/"},
{ id: 2, parent: 1, path: "/1/" },
{ id: 3, parent: 1, path: "/1/" },
{ id: 4, parent: 2, path: "/1/2/" },
{ id: 5, parent: 2, path: "/1/2/" },
{ id: 6, parent: 3, path: "/1/3/" },
{ id: 7, parent: 3, path: "/1/3/" },
{ id: 8, parent: 4, path: "/1/2/4/" },
{ id: 9, parent: 4, path: "/1/2/4/" },
{ id: 10, parent: 5, path: "/1/2/5/" },
{ id: 11, parent: 5, path: "/1/2/5/" },
{ id: 13, parent: 6, path: "/1/3/6/" },
{ id: 14, parent: 7, path: "/1/3/7/" },
...

這種的搜尋方式就更簡單了,我們只要利用在搜尋資料庫時對
path 欄位進行 Regular Expression ,找尋其 path 字串中擁有部分自己 path 字串的資料,就可以把下線全部抓出來了。

我們一樣以 2 為例好了。

由於 2 的 path“/1/2/” ,因此我們只要找尋 path 中有 “/1/2/” 的資料,即是: 4, 5, 8, 9, 10, 11

Regular Expression 可以這樣下: /^${this.path}.*/

結語

其實以上兩種方式的概念都是如出一徹的。

只是在 RDS 的資料儲存中,以 Array 的形式儲存 可能不是這麼方便 ,因此第二種會是不錯的選擇。

而若是資料庫為 mongodb 這類的 NoSQL,第一種就會是一個挺方便的做法。


原文出處:關於組織樹狀圖的資料結構設計方法 | by Les Lee | 一個小小工程師的隨手筆記 | Medium
內容圖示
url email imgsrc image code quote
樣本
bold italic underline linethrough   












 [詳情...]
validation picture

注意事項:
預覽不需輸入認證碼,僅真正發送文章時才會檢查驗證碼。
認證碼有效期10分鐘,若輸入資料超過10分鐘,請您備份內容後,重新整理本頁並貼回您的內容,再輸入驗證碼送出。

選項

Powered by XOOPS 2.0 © 2001-2008 The XOOPS Project|