2014-09-10 78 views
1

我在MongoDB中像這樣的造型兩種類型的事件(事件和子事件)的嵌入文檔:建模參考使用貓鼬

var EventSchema = mongoose.Schema({ 
    'name' : String, 
    'subEvent' : [ SubeventSchema ] 
}); 

var SubeventSchema = mongoose.Schema({ 
    'name' : String 
}); 

現在,當我查詢子事件我希望能夠還檢索數據關於其相應superevent,因此使用貓鼬種羣特徵可能看起來像這樣獲取的一些示例數據:

EventModel.findOne({ 
    name : 'Festival' 
}) 
.populate('subEvent') 
.execute(function (err, evt) { return evt; }); 

{ 
    name : 'Festival', 
    subEvent: [ 
     { name : 'First Concert' }, 
     { name : 'Second Concert' } 
    ] 
} 

EventModel.findOne({ 
    'subEvent.name' : 'FirstConcert' 
}, { 
    'subEvent.$' : 1 
}) 
.populate('superEvent') // This will not work, this is the actual problem of my question 
.execute(function (err, subevt) { return subevt; }); 

{ 
    name: 'First Concert', 
    superEvent: { 
     name: 'Festival' 
    } 
} 

一個解決方案,我能想到的是不嵌入,但引用這樣的:

var EventSchema = mongoose.Schema({ 
    'name' : String, 
    'subEvent' : [ { 
     'type' : mongoose.Schema.Types.ObjectId, 
     'ref' : 'SubeventSchema' 
    } ] 
}); 

var SubeventSchema = mongoose.Schema({ 
    'name' : String, 
    'superEvent' : { 
     'type' : mongoose.Schema.Types.ObjectId, 
     'ref' : 'EventSchema' 
    } 
}); 

雖然我正在尋找基於第一個使用嵌入子事件的示例的解決方案。這是否可以實現,如果是,如何?

回答

0

也許這是一種情況,你需要修改你的思想而不是模式本身。 Mongoose .populate()支持MongoDB「投影」的基本概念,或者更常見的稱爲「字段選擇」。因此,不要試圖對此進行建模,只需選擇要填充的字段。

所以你的第二個架構形式是完全有效的,只是改變你如何填充:

EventModel.find({}).populate("subEvent", "name").execute(function(err,docs) { 

    // "subevent" array items only contain "name" now 

}); 

這是貓鼬文檔中的實際覆蓋下的"populate"部分。

+0

感謝您的回覆!我已經閱讀了相應的文檔,您的解決方案實際上就是我在第二個示例中的含義。這會迫使我改變模式,這正是我的第一個例子。我會爲我的問題添加更多的細節。 – hielsnoppe 2014-09-10 12:11:39

+0

@hielsnoppe如果你真的希望,你可以離開並改變。但你的問題仍然基本上是「如何限制填充下的相關模式返回的字段」。這基本上是答案,沒有什麼會改變這一點。所以如果你想在你的相關模式中有更多的字段,那麼你將不得不添加它們。沒有別的方法,除非你的模式不是「嚴格」 – 2014-09-10 12:16:42

+0

所以你的意思是我將不得不添加一個'superEvent'字段到SubeventSchema引用子事件嵌入的事件?這似乎是多餘的,因爲協會應該通過嵌入來清楚,但如果沒有其他方式,我會這樣做。這也不能導致人口中的循環? – hielsnoppe 2014-09-10 12:27:13

2

我認爲你的文檔嵌入心智模型是不正確的。主要的誤解(這很常見)是你「查詢子事件」(查詢嵌入式文檔)。根據您當前的Event架構,Subevent只是嵌入在Event文檔中的文檔。嵌入式SubEvent不是頂級文檔;它不是MongoDB中任何集合的成員。因此,您不要查詢它。您查詢Event s(這是您的模式中的實際集合級文檔),其subEvents具有某些屬性。例如。單程人翻譯查詢

db.events.find({ "subEvent" : { "name" : "First Concert" } }) 

簡單易懂的英語是「找到所有與該名稱的子事件‘第一場演唱會’,這是錯誤的。正確的翻譯是」發現,至少有一個子事件,其所有活動名稱是「First Concert」(「至少有一個」部分取決於知識subEvent是一個數組)。

回到具體的問題,你可以希望現在看到,試圖在subevent上填充「superevent」是沒有意義的。您的查詢返回事件。最佳模式,無論是事件中嵌入的子事件,事件與子事件之間的單向還是雙向引用,都是單獨集合中的文檔,或非規範化爲子事件文檔的事件,無法根據問題中的信息確定,因爲用例是未標明。