2017-07-18 39 views
0

我試圖建立一個在CouchDB中有「關係」的網盤般的場景:具有三個實體(用戶,文件夾,文件)的CouchDB上的哪個數據結構?

  • 用戶
  • 文件夾
  • 文件

到目前爲止我struggeling是否引用或嵌入上述內容,尚未解決權限問題。在我的場景中,我只想存儲文件的路徑,而不想使用附件。下面是我有:

選項1(單獨的文件)

在這裏,我連鎖只是一切融合在一起,它(至少對我來說)似乎是一個RDBMS模型的副本這不應該是目標當使用NoSQL時。

{ 
    "id": "user1", 
    "type": "user", 
    "folders": [ 
     "folder1", 
     "folder2" 
    ] 
} 

{ 
    "id": "folder1", 
    "type": "folder", 
    "path": "\\user1\\pictures", 
    "files": [ 
     "file1", 
     "file2" 
    ] 
} 

{ 
    "id": "file1", 
    "type": "file", 
    "name": "myDoc.txt", 
} 

選項2(單獨的文件)

在此選項中我會離開的用戶文檔,因爲它是和放到文件夾中文件的用戶ID爲參考的目的。

{ 
    "id": "user1", 
    "type": "user", 
} 

{ 
    "id": "folder1", 
    "type": "folder", 
    "path": "\\user1\\pictures", 
    "owner" "user1", 
    "files": [ 
     "file1", 
     "file2" 
    ] 
} 

{ 
    "id": "file1", 
    "type": "file", 
    "name": "myDoc.txt", 
} 

選項3(嵌入式文件)

類似選項2我在這裏會駁回第三文檔類型文件並嵌入到一切文件夾的文件。我讀過這只是一個選項,如果我不需要存儲很多項目,並且我不知道用戶將存儲多少項目。

{ 
    "id": "user1", 
    "type": "user", 
} 

{ 
    "id": "folder1", 
    "type": "folder", 
    "path": "\\user1\\pictures", 
    "owner" "user1", 
    "files": [{ 
      "id": "file1", 
      "type": "file", 
      "name": "myDoc1.txt" 
     }, { 
      "id": "file2", 
      "type": "file", 
      "name": "myDoc2.txt" 
     } 
    ] 
} 

選項4

我也可以把一切都只是一個文件,但在這種情況下這是沒有意義的。 JSON文檔會在時間上變得很大,這對於性能/加載時間來說並不合適。

結論

對我來說沒有任何上述選項似乎適合我的方案,我希望聽取您如何在CouchDB的設計合適的數據庫架構一些輸入。或者,也許上述選項之一已經是一個好的開始,我只是沒有看到它。

+0

如果以上選項都不符合您的方案,也許CouchDB不是您應該使用的數據庫類型?此外,我假設查詢需要非常重要,因爲用戶可能希望查找某些文件,無論文件夾的級別如何。除非您使用#1選項,否則使用CouchDB時速度會非常慢。 –

+0

這並不是說他們不適合我的場景,更像是我需要一些指導來選擇合適的設計。一般來說,我對CouchDB和NoSQL相當陌生。在我的項目中,我必須使用CouchDB。現在我認爲選項1將是開始時的方式,並看看它是否有效。 – Magiranu

+0

根據我的經驗,我們傾向於儘可能多地嵌套文檔以避免關係。因此,有些情況下這沒有任何意義。如果有時可以有一些「關係」。在你的情況下,唯一可行的解​​決方案將是1. –

回答

1

爲您提供一個具體的想法,我會一個Dropbox的克隆莫名其妙模型是這樣的:

  • 股:該共享的根文件夾。沒有必要爲子文件夾建模,因爲它們沒有不同的權限。在這裏,我可以設置文件夾的物理位置以及允許使用它們的用戶。我希望每個用戶只有少數份額,所以你可以保留內存中的份額清單。
  • 文件:共享中的實際文件。根據您的使用情況,不需要將文件保存在數據庫中,因爲文件系統本身已經是一個很好的文件數據庫!如果您需要散列和重複數據刪除文件(如Dropbox這樣做),那麼您可以在CouchDB中創建一個緩存。

這將是文檔結構:

{ 
    "_id": "share.pictures", 
    "type": "share", 
    "owner": "Alice", 
    "writers": ["Bob", "Carl"], 
    "readers": ["Dorie", "Eve", "Fred"], 
    "rootPath": "\\user1\pictures" 
}, 

{ 
    "_id": "file.2z32236e2sdwhatever", 
    "type": "file", 
    "path": ["vacations", "2017 maui"], 
    "filename": "DSC1234.jpg", 
    "size": 12356789, 
    "hash": "1235a", 
    "createdAt": "2017-07-29T15:03:20.000Z", 
    "share": "share.pictures" 
}, 

{ 
    "_id": "file.sdfwhatever", 
    "type": "file", 
    "path": ["vacations", "2015 alaska"], 
    "filename": "DSC12345.jpg", 
    "size": 11, 
    "hash": "acd5a", 
    "createdAt": "2017-07-29T15:03:20.000Z", 
    "share": "share.pictures" 
} 

這樣你就可以建立通過共享和路徑文件的CouchDB的視圖和文件夾進行查詢:

function (doc) { 
    if (doc.type === 'file') emit([doc.share].concat(doc.path), doc.size); 
} 

如果你想,你可以添加一個減少函數,只需要_sum,並免費獲得分層大小的計算器(好,差不多)!

假設你叫數據庫「dropclone」,並添加視圖,以所謂的「dropclone」與視圖名稱「文件」設計文檔,你會質疑這樣的:

http://localhost:5984/dropclone/_design/dropclone/_view/files?key=["share.pictures","vacations"] 

你會得到123456800作爲結果。

對於 http://localhost:5984/dropclone/_design/dropclone/_view/files?key=[ 「share.pictures」, 「度假」] &減少=假& include_docs =真

你會得到兩個文件作爲一個結果。

您還可以將整個共享名稱和路徑添加到_id中,因爲那樣您就可以直接通過已知路徑訪問每個文件。您仍然可以冗餘地添加路徑或將其保留並僅將_id動態分割爲其路徑組件。

其他方法是:

  • 使用一個CouchDB的每股數據庫,並使用CouchDB的_security機制來管理訪問。
  • 將文件拆分成塊,對它們進行散列並存儲每個文件的塊散列。通過這種方式,您可以對完整的文件系統進行虛擬化和重複數據刪除。這就是Dropbox在後臺執行的操作,以節省存儲空間。

你不應該做的一件事是將文件本身存儲到CouchDB中,這將很快變髒。 NPM不得不在幾年前經歷過這樣的事情,他們不得不在一次巨大的工程努力中擺脫這種模式。

+1

我故意排除了用戶。您可以使用_users數據庫來存儲私人用戶數據。如果您想顯示公開個人資料,那麼將這些公開個人資料放入另一個數據庫是有意義的。 –

+0

請問爲什麼你忽略了用戶文件夾的json文檔?或者「共享」文檔是兩者的組合,有關文件夾和權限的信息? – Magiranu

+1

如果您建模類似Dropbox的場景,則僅在共享級別上給出權限,而不是在文件夾級別上。這首先是一個約束,但是使權限處理起來更容易(否則,您將不得不遞歸地將權限應用於黑名單/白名單,這很快就會變得討厭)。考慮到這一點,文件夾只是文件的分組(想像它就像git那樣)。如果你真的想要空文件夾,那麼你可以創建單獨的文件夾文件,但要注意不應該需要文件夾(如果存在不存在文件夾的文件,該怎麼辦?) –

1

數據建模開始於應用程序將使用的查詢。 如果您的查詢將是用戶看到他/她的所有文件夾,並打開一個文件夾顯示其下的所有文檔和子文件夾,則選項1適合查詢。

但是,首先需要回答一個非常重要的問題,尤其是對於CouchDB。你的數據庫將會是多大?如果您需要跨多個節點進行分區的數據庫,則性能會受到影響,可能會導致數據庫無法響應。因爲用許多文檔打開文件夾將意味着搜索每個分區。這是由於分區由用戶無法控制的ID的散列決定的。對於小型單節點(或非分區)數據庫,性能會很好。

選項2,需要你的「老闆」,它遭受了同樣的理由,選擇1

選項3/4是一種非規範化的,其解決上述性能問題建立索引。如果文檔很大並經常更新,存儲和壓縮成本的開銷可能會很大。您需要針對您的特定工作負載進行基準測試。

總之,如果你的目標數據庫會很大並且被分區,那麼就沒有簡單的答案。需要仔細的原型和基準標記。

+0

你的文章闡明瞭我面臨的整體問題。關於DB分配,我也沒有想到。這是一個非常好的提示!順便說一下,感謝您將第一篇文章獻給我的問題;-) – Magiranu

相關問題