2013-03-02 27 views
-1

考慮以下數據結構對於一次存儲在數據庫系統(rdbms或nosql)中的數據,QUERY會更好嗎?元數據字段中的字段是用戶定義的,因用戶而異。可能的值是字符串,數字,「日期」或甚至數組。mongodb(或其他nosql dbs)是以下場景的最佳解決方案嗎?

var file1 = { 
    id: 123, name: "mypicture", owner: 1 
    metadata: { 
     people: ["Ben", "Tom"], 
     created: 2013/01/01, 
     license: "free", 
     rating: 4 
     ... 
    }, 
    tags: ["tag1", "tag2", "tag3", "tag4"] 
} 

var file2 = { 
    id: 155, name: "otherpicture", owner: 1 
    metadata: { 
     people: ["Tom", "Carla"], 
     created: 2013/02/02, 
     license: "free", 
     rating: 4 
     ... 
    }, 
    tags: ["tag4", "tag5"] 
} 

var file1OtherUser = { 
    id: 345, name: "mydocument", owner: 2 
    metadata: { 
     autors: ["Mike"], 
     published: 2013/02/02, 
     …  
    }, 
    tags: ["othertag"] 
} 

我們的用戶應該有搜索/過濾文件的功能:

  • 用戶1:顯示所有文件,其中「湯」是「人」的陣列
  • 用戶1:顯示全部創建「2013/01/01至2013/02/01之間的文件」
  • 用戶1:在「2012」中標註爲「重要」
  • ...

結果應該像這樣,你可以在OS X做智能文件夾進行過濾。各個元數據字段在文件上傳/存儲之前定義。但是之後它們也可能改變,例如用戶1可以將元數據字段「people」重命名爲「cast」。

+0

如果這些字段是可變的,那麼您將無法有效地對字段建立索引,因爲mongodb集合中的索引總數不僅有64個,而且還有一個總體建議對於MongoDb,您可能需要將結構扁平化以在鍵入或索引的集合中具有鍵和值。你有沒有考慮過如何用數據做MapReduce? – WiredPrairie 2013-03-02 13:08:00

+0

我提出一個類型化索引的原因是,所有的特定索引值都是相同的。 – WiredPrairie 2013-03-02 13:10:54

回答

0

正如@WiredPrairie表示,metadata場看變量中的領域,也許取決於用戶輸入什麼它支持:

用戶1可以重命名元數據字段「人」,以「鑄造」 。

MongoDB的,由此你剛纔說,在metadata每一個新的領域被添加到複合索引,但是你可以做一個鍵值式結構,像這樣不能創建變量指標:

var file1 = { 
    id: 123, name: "mypicture", owner: 1 
    metadata: [ 
     {k: people, v:["Ben", "Tom"]}, 
     {k: created, v:2013/01/01}, 
    ], 
    tags: ["tag1", "tag2", "tag3", "tag4"] 
} 

也就是說這樣做的一種方法,允許您在metadata字段內動態索引kv。然後你會這樣查詢:

db.col.find({metadata:{$elemMatch:{k:people,v:["Ben"]}}}) 

但是這確實會引入另一個問題。 $elemMatch適用於頂層,而不是嵌套的元素。想象一下,你想找到這裏的「本」是people之一的所有文件,則不能使用$elemMatch這裏,所以你必須做的:

db.col.find({metadata.k:people,metadata.v:"Ben"}) 

該查詢的迫在眉睫的問題是這樣的MongoDB查詢。當它查詢metadata字段時,將會說:其中「k」的一個字段等於「people」並且字段「v」等於「Ben」

由於這是一個多值字段,所以即使「Ben」不在人羣列表中,因爲他存在於metadata的另一個字段中,您實際上會挑出錯誤的文檔;即,該查詢將回暖:

var file1 = { 
    id: 123, name: "mypicture", owner: 1 
    metadata: [ 
     {k: people, v:["Tom"]}, 
     {k: created, v:2013/01/01}, 
     {k: person, v: "Ben"} 
    ], 
    tags: ["tag1", "tag2", "tag3", "tag4"] 
} 

解決這個問題的唯一現實的辦法就是關因素的動態領域到另一個集合,其中你沒有這個問題。

雖然這會產生一個新問題,但您無法再單次往返獲取完整文件,也無法一次性聚合文件行及其用戶定義的字段。總而言之,通過這個東西你會失去很多能力。

話雖這麼說,你仍然可以執行相當多的疑問,即:

  • 用戶1:顯示所有文件,其中「湯」是「人」的陣列
  • 用戶1:顯示所有文件「創建「2013年1月1日至2013年2月1日之間
  • 用戶1:顯示」許可「」免費「和」評級「更大的所有文件2
  • 用戶2:顯示」 2012「並標記爲」重要「

所有這些仍然可以用這個模式。

至於哪個更好-RDBMS或NoSQL;這裏很難說,如果做得對,我可以說兩者都可以相當好,以查詢這種結構。

+0

感謝您的回答。我如何確定元數據字段的類型(字符串,數字,日期)以便在gui中正確顯示它,例如日期選擇器?我想我需要將這個類型與每個條目一起存儲,對吧? 我想聽到更多的意見,特別是喜歡關係解決方案的人。 (到目前爲止,我還是不會回答這個問題。) – joafeldmann 2013-03-02 14:37:36

+0

@joafeldmann這取決於你如何在你的界面中使用它,你可能會被要求,但更多的是你測試返回的字段的值,看看它是什麼。 – Sammaye 2013-03-02 14:40:27