使用Mongoosebuild模embedded文档的build模参考

我在MongoDB中对两类事件(事件和子事件)进行build模,如下所示:

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

现在,当我查询一个子事件时,我希望能够检索其相应的超级事件的数据,以便使用Mongoose人口特征检索到的一些示例数据如下所示:

 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' } } 

我能想到的解决scheme不是embedded,而是像这样引用:

 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' } }); 

不过,我正在寻找一个基于使用embedded子事件的第一个示例的解决scheme。 可以这样做,如果是的话,怎么样?

我认为你的文件embedded的心理模型是不正确的。 主要的误解(这是非常普遍的)是你“查询子事件”(查询embedded式文档)。 根据您当前的Event模式,一个Subevent只是一个embeddedEvent文档中的文档。 embedded的SubEvent不是顶层文档; 它不是MongoDB中的任何集合的成员。 因此,您不要查询它。 您查询Event s(这是您的模式中的实际集合级文档),其子subEvents具有某些属性。 例如,人们翻译查询的方式之一

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

就是“find所有名字为”First Concert“的子事件,这是错误的,正确的翻译是”find所有至less有一个子事件名为“First Concert”的事件(“至less有一个”部分依赖于知识subEvent是一个数组)。

回到具体的问题,你可以希望现在看到,试图在一个子事件中填充“超级预防”是没有意义的。 您的查询返回事件。 最佳模式,无论是事件中embedded的子事件,事件与子事件之间的单向还是双向引用,都是单独集合中的文档,或者非正规化为子事件文档的事件,不能从问题中的信息中确定,因为用例是未标明。

也许这是一种情况,你需要修改你的思维而不是模式本身。 Mongoose .populate()支持MongoDB“投影”的基本概念,或者更一般地被称为“字段select”。 因此,不要试图对此进行build模,只需select要填充的字段即可。

所以你的第二个模式forms是完全有效的,只是改变你如何填充:

 EventModel.find({}).populate("subEvent", "name").execute(function(err,docs) { // "subevent" array items only contain "name" now }); 

这实际上是在“填充”部分下的Mongoose文档中介绍的。