不确定这是否会被视为重复,但我已经搜索过并对我在网上找到的内容进行了类似的查询,但似乎无法让我的嵌套引用工作。我只是测试了解用于填充嵌套引用和嵌套文档的mongoose语法,如下所述:Mongoose nested schema vs nested models
但是,我必须遗漏一些东西,因为它似乎工作但返回一个空的嵌套引用数组。我知道我的查询应该为嵌套引用返回两个结果。
数据:
结果收集:
{
"_id" : ObjectId("5a4dcbe4ab9a793d888c9396"),
"event_id" : ObjectId("5a482302a469a068edc004e3"),
"event_name" : "Sample Event",
"score" : "3-2",
"winner" : "player1"
},
{
"_id" : ObjectId("5a59791379cc1c321c1918f0"),
"event_id" : ObjectId("5a482302a469a068edc004e3"),
"event_name" : "Sample Event",
"score" : "2-1",
"winner" : "player2"
}
活动收集:
{
"_id" : ObjectId("5a482302a469a068edc004e3"),
"type" : "Tournament",
"name" : "Sample Event"
}
我的代码如下:
var mongoose = require("mongoose");
mongoose.connect("MongoDB://localhost/devDB");
var ResultSchema = mongoose.Schema({
_id: mongoose.Schema.Types.ObjectId,
event_id: {type: mongoose.Schema.Types.ObjectId, ref: "EventModel"},
event_name: String,
score: String,
winner: String
});
var ResultModel = mongoose.model("results", ResultSchema);
var EventSchema = mongoose.Schema({
_id: mongoose.Schema.Types.ObjectId,
name: String,
type: String,
results: [{type: mongoose.Schema.Types.ObjectId, ref: "ResultModel"}]
});
var EventModel = mongoose.model("events", EventSchema);
function GetEvent(eventid){
// EventModel.findById(eventid)
EventModel.findOne({_id: eventid})
.populate("results","score winner", ResultModel)
//.select("results") to extract only the nested references
.exec(function(err, event){
if (err){
console.log("ERROR fetching doc: ", err.name + ": " + err.message)
} else{
console.log(event);
}
});
}
GetEvent("5a482302a469a068edc004e3");
我运行时的输出:
{
results: [],
_id: 5a482302a469a068edc004e3,
type: 'Tournament',
name: 'Test Tournament'
}
答案 0 :(得分:1)
您的代码的问题是您的results
数组缺少填充数组所必需的ObjectIds。您目前正在将这些集合与结果文档中的event_id
连接在一起。它们指的是事件集合中的文档。但是,当您在事件集合上进行填充时,它希望引用位于results
数组中。
以这些值为例:
<强>结果:强>
{
"_id" : ObjectId("5a5be9a4669365067f984acb"),
"event_name" : "Game 1",
"score" : "1-2",
"winner" : "ManU",
"event_id" : ObjectId("5a5be9d9669365067f984acd")
}
{
"_id" : ObjectId("5a5be9b5669365067f984acc"),
"event_name" : "Game 2",
"score" : "3-2",
"winner" : "Bayern Munich",
"event_id" : ObjectId("5a5be9d9669365067f984acd")
}
<强>活动:强>
{
"_id" : ObjectId("5a5be9d9669365067f984acd"),
"name" : "Champions League",
"type" : "Cup",
"results" : [
ObjectId("5a5be9a4669365067f984acb"),
ObjectId("5a5be9b5669365067f984acc")
]
}
我已使用MongoDB shell手动插入文档。请注意,结果文档的objectIds存储在results
数组中。如果我现在运行此代码:
const mongoose = require("mongoose");
mongoose.connect("mongodb://localhost/devDB");
const ResultSchema = mongoose.Schema({
event_id: {type: mongoose.Schema.Types.ObjectId, ref: "events"},
event_name: String,
score: String,
winner: String
});
const Results = mongoose.model("results", ResultSchema);
const EventSchema = mongoose.Schema({
name: String,
type: String,
results: [{type: mongoose.Schema.Types.ObjectId, ref: "results"}]
});
const Events = mongoose.model("events", EventSchema);
function GetEvent(eventid){
Events.findOne({_id: eventid})
.populate("results", "score winner")
.exec(function(err, event){
if (err){
console.log("ERROR fetching doc: ", err.name + ": " + err.message)
} else{
console.log(event);
}
});
}
GetEvent("5a5be9d9669365067f984acd");
我得到以下输出:
{ _id: 5a5be9d9669365067f984acd,
name: 'Champions League',
type: 'Cup',
results:
[ { _id: 5a5be9a4669365067f984acb, score: '1-2', winner: 'ManU' },
{ _id: 5a5be9b5669365067f984acc,
score: '3-2',
winner: 'Bayern Munich' } ] }
显示填充的结果,因为results
数组实际上包含对结果对象的引用。 populate方法查找文档的集合在ref
中给出。其中的值是已注册模型的名称,即您作为mongoose.model()
的第一个参数给出的名称。
您还使用event_id
引用结果文档中的事件。您在问题中使用的代码并不是真的需要,但如果您想要双向连接(结果&lt; - &gt;事件),您可以保留它。然后,您可以创建如下函数:
function GetResult(resultid){
Results.findOne({_id: resultid})
.populate("event_id", "name type")
.exec(function(err, result){
if (err){
console.log("ERROR fetching doc: ", err.name + ": " + err.message)
} else{
console.log(result);
}
});
}
像这样执行
GetResult("5a5be9b5669365067f984acc");
它会给我们这个结果:
{ _id: 5a5be9b5669365067f984acc,
event_name: 'Game 2',
score: '3-2',
winner: 'Bayern Munich',
event_id:
{ _id: 5a5be9d9669365067f984acd,
name: 'Champions League',
type: 'Cup' } }
对于嵌套模型(嵌入),您不再将objectIds存储到文档中的其他集合。您将整个文档存储为子文档。以此代码为例:
const mongoose = require("mongoose");
mongoose.connect("mongodb://localhost/devDB");
const ResultSchema = mongoose.Schema({
event_name: String,
score: String,
winner: String
});
// Don't register subdocuments!
// const Results = mongoose.model("results", ResultSchema);
const EventSchema = mongoose.Schema({
name: String,
type: String,
results: [ResultSchema]
});
const Events = mongoose.model("events", EventSchema);
function GetEvent(eventid){
Events.findOne({_id: eventid})
// We no longer use populate.
// .populate("results", "score winner")
.exec(function(err, event){
if (err){
console.log("ERROR fetching doc: ", err.name + ": " + err.message)
} else{
console.log(event);
}
});
}
GetEvent("5a5bf133669365067f984ace");
我们现在将整个结果模式存储在事件模式中。在这种特殊情况下,它是一个数组,但它并不是必须的。结果集将不再存在。结果存储在事件文档中。确保您没有注册子文档模式。 event_id
也没有意义,所以我删除了它。
我使用MongoDB shell重新插入数据:
{
"_id" : ObjectId("5a5bf133669365067f984ace"),
"name" : "Champions League",
"type" : "Cup",
"results" : [
{
"event_name" : "Game 1",
"score" : "3-2",
"winner" : "ManU"
},
{
"event_name" : "Game 2",
"score" : "1-2",
"winner" : "Real Madrid"
}
]
}
当我使用GetEvents("5a5bf133669365067f984ace")
时,我得到:
{ _id: 5a5bf133669365067f984ace,
name: 'Champions League',
type: 'Cup',
results:
[ { event_name: 'Game 1', score: '3-2', winner: 'ManU' },
{ event_name: 'Game 2', score: '1-2', winner: 'Real Madrid' } ] }