2016-02-11 53 views
1

我有一個人的集合。每個人可能有很多書。每本書都有一個被撤回的日期。MongoDB架構建議重新:嵌入文件

這是我第一次使用來自傳統SQL的Mongo。我的第一意見是讓每本書都撤回一份子文件。但是,這似乎使子文檔的排序很痛苦。

事情是這樣的,例如:

例如,如果我想獲得的是已撤回一書時,他們撤回了命令的人的名單,我覺得跟蒙​​戈是變得非常複雜。

我應該使用引用並從Person集合中拆分撤銷?

感謝您的任何建議。

回答

1

如果我理解正確的話,在你Person集合中的每個文件看起來是這樣的 -

{ 
    name: String, 
    withdrawals: [ 
    { 
     bookName: String, 
     withdrawalDate: Date 
    }, 
    { 
     bookName: String, 
     withdrawalDate: Date 
    } 
    . 
    . 
    . 
    ] 
} 

如果是這樣的話,我相信你可以使用下面的查詢來獲取誰借的所有的人的名單一個特定的書(book1在這個例子中)按照提款日期的升序排列。

Person.find({ "withdrawals.bookName": "book1" }, { 
    sort: { "withdrawals.withdrawalDate": 1 } 
}); 
+0

嗨 謝謝您的答覆。我正在尋找的結果是這樣的: {「_id」:ObjectId(「whatever」),「name」:「Bob」,「withdrawl」:[{「name」:「book1」,THIS BIT ORDERED「withdrawlDate」:ISODate(最早)} 因此,嵌入文檔本身的排序與主文檔的排序無關,如果有意義的話? – user1496093

+0

是的,嵌入文檔的順序與主排序順序無關。上面的查詢按照特定書名的提款日期升序對Person文檔進行排序。如果這不是您正在查找的查詢,請您詳細說明您在此嘗試實現的目標嗎? – umesh

2

Overembedding is the root of all evil.

上有16MB的BSON文件爲寫這篇文章(以及可預見的未來)的時間大小限制。如果你真的想讓一個人擁有無限的書籍,你就不能嵌入書籍。這同樣適用於取款次數。

我們這裏有一個衆所周知的模式,與屬性的關係,這意味着關係本身通過附加屬性進行限定。

所以你想在這裏有一個persons收集,與人的所有數據,書籍收集與書籍的所有數據和提款收集來記錄誰借了哪本書在哪一天(甚至可能會返回它)。

這是由於您的使用情況下,基本上是這樣的:

  1. 對於一個給定的,是它可用? (=沒有公開撤回)
  2. 對於給出退出,誰借了書?
  3. 對於一個給定的用戶書並給予日期,文件撤回。
  4. 對於一個給定的用戶書並給予日期,記錄了回報。

藏品

所以你person集合的存根看起來像

{ 
    _id: new ObjectId() 
    username: "foo", 
    … 
} 

你的藏書類似於:

{ 
    _id: "someISBN" 
    title: "Foobar and Barbaz explore the Mongoverse" 
    … 
} 

提款文件看起來是這樣的:

{ 
    _id: new ObjectId(), 
    userId: someUserObjectId, 
    bookId: someBookId, 
    withdrawalDate: new ISODate(), 
    // returnDate can be omitted, too 
    // since non-existing values evaluate to null 
    returnDate: null 
} 

可用性檢查

現在,讓我們說有人發現了一本書,他或她想要退出,你找出羯羊它可通過發出

> db.withdrawals.find({bookId:someBookId,returnDate:null}) 
{ "_id" : ObjectId("56bc6c8188d0e8d074b11a8d"), "userId" : ObjectId("56bc6bd888d0e8d074b11a8a"), "bookId" : "1234567890", "withdrawalDate" : ISODate("2016-02-11T11:12:01.325Z") } 

如果此查詢找到的東西,這本書是但是借來的還沒有歸還。如果沒有文件被退回,你會知道該書應該可用。

:與文檔回來,你現在可以找出誰通過查詢persons收集借的書,因爲我們有用戶名:

> db.persons.find({_id:ObjectId("56bc6bd888d0e8d074b11a8a")}) 
{ "_id" : ObjectId("56bc6bd888d0e8d074b11a8a"), "username" : "mwm" } 

提款和返回

當用戶「mwm」借了書,它被記錄在最簡單的方式:

db.withdrawals.insert({ 
    userId:ObjectId("56bc6bd888d0e8d074b11a8a"), 
    bookId:"0987654321", 
    withdrawalDate:new ISODate("2016-01-01T12:00:00Z") 
    }) 

現在,當(已知)博由(已知)用戶返回OK,記錄它是非常容易的:Umesh製作

db.withdrawals.update(
{ 
    "userId":ObjectId("56bc6bd888d0e8d074b11a8a"), 
    "bookId":"0987654321" 
},{ 
    $set:{ returnDate: newISODate() } 
}) 
+0

非常感謝markus提供了這樣一個全面的答案。我一定會嘗試這個。 – user1496093