猫鼬嵌套模型
Mongoose nested model
不确定这是否会被视为重复,但我四处搜索并实现了与我在网上找到的内容类似的查询,但似乎无法使我的嵌套引用起作用。我只是在测试以了解用于填充嵌套引用和嵌套文档的 mongoose 语法,如下所述:Mongoose nested schema vs nested models
但是,我一定是遗漏了一些东西,因为它似乎可以工作,但是 return 是一个空的嵌套引用数组。我知道我的查询应该 return 嵌套引用的两个结果。
- 我忽略了什么或做错了什么?
- 如果我想使用嵌套文档,我的查询 运行 会有什么不同?
数据:
结果合集:
{
"_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'
}
您的代码存在的问题是您的 results
数组缺少填充数组所需的 ObjectId。您当前正在将集合与结果文档中的 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 的文档。请注意,结果文档的 objectId 存储在 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
数组实际上包含对结果对象的引用。填充方法在其中查找文档的集合在 ref
中给出。那里的值是注册模型的名称,即您作为 mongoose.model()
.
的第一个参数给出的名称
您还使用 event_id
引用了结果文档中的事件。您问题中的代码并不是真正需要它,但是如果您想双向建立连接(结果 <--> 事件),您可以保留它。然后你可以像这样创建一个函数:
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' } }
对于嵌套模型(嵌入),您不再将 objectId 存储到文档中的其他集合。您将整个文档存储为子文档。以这段代码为例:
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' } ] }
不确定这是否会被视为重复,但我四处搜索并实现了与我在网上找到的内容类似的查询,但似乎无法使我的嵌套引用起作用。我只是在测试以了解用于填充嵌套引用和嵌套文档的 mongoose 语法,如下所述:Mongoose nested schema vs nested models
但是,我一定是遗漏了一些东西,因为它似乎可以工作,但是 return 是一个空的嵌套引用数组。我知道我的查询应该 return 嵌套引用的两个结果。
- 我忽略了什么或做错了什么?
- 如果我想使用嵌套文档,我的查询 运行 会有什么不同?
数据:
结果合集:
{
"_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'
}
您的代码存在的问题是您的 results
数组缺少填充数组所需的 ObjectId。您当前正在将集合与结果文档中的 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 的文档。请注意,结果文档的 objectId 存储在 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
数组实际上包含对结果对象的引用。填充方法在其中查找文档的集合在 ref
中给出。那里的值是注册模型的名称,即您作为 mongoose.model()
.
您还使用 event_id
引用了结果文档中的事件。您问题中的代码并不是真正需要它,但是如果您想双向建立连接(结果 <--> 事件),您可以保留它。然后你可以像这样创建一个函数:
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' } }
对于嵌套模型(嵌入),您不再将 objectId 存储到文档中的其他集合。您将整个文档存储为子文档。以这段代码为例:
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' } ] }