我在MongoDB中建模两种类型的事件(事件和子事件),如下所示:
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'
}
}
我能想到的解决方案不是嵌入,而是像这样引用:
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 :(得分:2)
我认为你的文档嵌入心理模型不正确。主要的误解(这是非常常见的)是你“查询子事件”(查询嵌入文档)。根据您当前的Event
架构,Subevent
只是嵌入在Event
文档中的文档。嵌入式SubEvent
不是顶级文档;它不是MongoDB中任何集合的成员。因此,您不会查询它。您查询Event
具有某些属性的subEvents
(模式中的实际集合级文档)。例如。人们翻译查询的一种方式
db.events.find({ "subEvent" : { "name" : "First Concert" } })
进入简单的英语是“找到所有名为”First Concert“的子事件。这是错误的。正确的翻译是”找到所有至少有一个子事件,其名称为“First Concert”的事件(“at”至少有一个“部分取决于subEvent
是一个数组的知识。”
回到具体问题,你现在可以看到,试图在子事件中填充“超级预防”毫无意义。您的查询返回事件。最佳模式,无论是事件中嵌入的子事件,事件和子事件之间的单向或双向引用,单独集合中的文档,还是非规范化为组成子事件文档的事件,都无法根据问题中的信息确定,因为用例是未指定。
答案 1 :(得分:0)
也许这是一种需要修改思路而非模式本身的情况。 Mongoose .populate()
支持MongoDB“投影”的基本思想,或者更常被称为“字段选择”。因此,不要试图围绕这个进行建模,只需选择要填充的字段。
因此,您的第二个架构表单完全有效,只需更改填充方式:
EventModel.find({}).populate("subEvent", "name").execute(function(err,docs) {
// "subevent" array items only contain "name" now
});
这实际上已在"populate"部分的Mongoose文档中介绍。