Mongodb 为什么Mongoose既有模式又有模型?
这两种类型的对象似乎彼此非常接近,以至于两者都感觉多余。同时拥有模式和模型有什么意义?编辑:尽管这对很多人都很有用,正如评论中提到的,它回答了“如何”而不是为什么。谢天谢地,这个问题的原因也在其他地方得到了回答。这一点在评论中已经联系了一段时间,但我意识到很多人在阅读时可能不会走那么远 通常,回答这类问题的最简单方法是举个例子。在这种情况下,有人已经为我做了:) 请看这里: 编辑:原始帖子(如评论中所述)似乎不再存在,因此我在下面复制它。如果它回来了,或者它刚搬走,请告诉我 它对在mongoose中的模型中使用模式以及您希望这样做的原因进行了恰当的描述,还向您展示了如何通过模型推送任务,而模式与结构等有关 原创帖子: 让我们从一个在模型中嵌入模式的简单示例开始Mongodb 为什么Mongoose既有模式又有模型?,mongodb,mongoose,Mongodb,Mongoose,这两种类型的对象似乎彼此非常接近,以至于两者都感觉多余。同时拥有模式和模型有什么意义?编辑:尽管这对很多人都很有用,正如评论中提到的,它回答了“如何”而不是为什么。谢天谢地,这个问题的原因也在其他地方得到了回答。这一点在评论中已经联系了一段时间,但我意识到很多人在阅读时可能不会走那么远 通常,回答这类问题的最简单方法是举个例子。在这种情况下,有人已经为我做了:) 请看这里: 编辑:原始帖子(如评论中所述)似乎不再存在,因此我在下面复制它。如果它回来了,或者它刚搬走,请告诉我 它对在mongoo
var TaskSchema = new Schema({
name: String,
priority: Number
});
TaskSchema.virtual('nameandpriority')
.get( function () {
return this.name + '(' + this.priority + ')';
});
TaskSchema.method('isHighPriority', function() {
if(this.priority === 1) {
return true;
} else {
return false;
}
});
var ListSchema = new Schema({
name: String,
tasks: [TaskSchema]
});
mongoose.model('List', ListSchema);
var List = mongoose.model('List');
var sampleList = new List({name:'Sample List'});
我用任务可能具有的基本信息创建了一个新的TaskSchema
对象。Mongoose设置为方便地组合任务的名称和优先级。我在这里只指定了一个getter,但也支持虚拟setter
我还定义了一个简单的任务方法,名为isHighPriority
,以演示这些方法如何使用此设置
在ListSchema
定义中,您会注意到tasks键是如何配置为容纳TaskSchema
对象数组的。任务键将成为一个实例,它提供了处理嵌入式Mongo文档的特殊方法
目前,我只将ListSchema
对象传递到mongoose.model中,而将TaskSchema保留在外。从技术上讲,没有必要将TaskSchema
转换为正式模型,因为我们不会将其保存在它自己的集合中。稍后,我将向您展示,如果您这样做,它将不会损害任何东西,并且它可以帮助您以相同的方式组织所有模型,尤其是当它们开始跨越多个文件时
使用列表
模型设置,让我们向其中添加几个任务,并将它们保存到Mongo
var List = mongoose.model('List');
var sampleList = new List({name:'Sample List'});
sampleList.tasks.push(
{name:'task one', priority:1},
{name:'task two', priority:5}
);
sampleList.save(function(err) {
if (err) {
console.log('error adding new list');
console.log(err);
} else {
console.log('new list successfully saved');
}
});
我们的列表
模型(simpleList
)实例上的tasks属性的工作方式与常规JavaScript数组类似,我们可以使用push向其添加新任务。需要注意的重要一点是,任务是作为常规JavaScript对象添加的。这是一个微妙的区别,可能不是直观的
您可以从Mongo shell验证新列表和任务是否已保存到Mongo
db.lists.find()
{ "tasks" : [
{
"_id" : ObjectId("4dd1cbeed77909f507000002"),
"priority" : 1,
"name" : "task one"
},
{
"_id" : ObjectId("4dd1cbeed77909f507000003"),
"priority" : 5,
"name" : "task two"
}
], "_id" : ObjectId("4dd1cbeed77909f507000001"), "name" : "Sample List" }
现在,我们可以使用ObjectId
来调出示例列表
,并迭代它的任务
List.findById('4dd1cbeed77909f507000001', function(err, list) {
console.log(list.name + ' retrieved');
list.tasks.forEach(function(task, index, array) {
console.log(task.name);
console.log(task.nameandpriority);
console.log(task.isHighPriority());
});
});
如果您运行最后一位代码,您将得到一个错误,说明嵌入的文档没有方法isHighPriority
。在当前版本的Mongoose中,您不能直接访问嵌入模式上的方法。在向猫鼬谷歌集团提出这个问题后,manimal45发布了一个有用的解决方案,目前可以使用
List.findById('4dd1cbeed77909f507000001', function(err, list) {
console.log(list.name + ' retrieved');
list.tasks.forEach(function(task, index, array) {
console.log(task.name);
console.log(task.nameandpriority);
console.log(task._schema.methods.isHighPriority.apply(task));
});
});
如果运行该代码,您将在命令行上看到以下输出
Sample List retrieved
task one
task one (1)
true
task two
task two (5)
false
考虑到这一点,让我们将TaskSchema
转换为Mongoose模型
mongoose.model('Task', TaskSchema);
var Task = mongoose.model('Task');
var ListSchema = new Schema({
name: String,
tasks: [Task.schema]
});
mongoose.model('List', ListSchema);
var List = mongoose.model('List');
TaskSchema
定义与以前相同,因此我将其省略。一旦它变成一个模型,我们仍然可以使用点符号访问它的底层模式对象
让我们创建一个新列表,并在其中嵌入两个任务模型实例
var demoList = new List({name:'Demo List'});
var taskThree = new Task({name:'task three', priority:10});
var taskFour = new Task({name:'task four', priority:11});
demoList.tasks.push(taskThree.toObject(), taskFour.toObject());
demoList.save(function(err) {
if (err) {
console.log('error adding new list');
console.log(err);
} else {
console.log('new list successfully saved');
}
});
当我们将任务模型实例嵌入到列表中时,我们对它们调用toObject
,将它们的数据转换为列表.tasks
objectid
完整的代码示例如下所示。随着猫鼬的不断发展,希望这些解决办法能帮助事情顺利进行。我对Mongoose和MongoDB还很陌生,所以请在评论中分享更好的解决方案和技巧。快乐数据建模 Schema是一个对象,用于定义将存储在MongoDB集合中的任何文档的结构;它使您能够为所有数据项定义类型和验证器 Model是一个对象,它使您能够轻松访问命名集合,允许您查询集合并使用架构验证保存到该集合的任何文档。它是通过组合架构、连接和集合名称创建的
瓦莱里·卡尔波夫(Valeri Karpov)最初的措辞是,我认为公认的答案实际上并没有回答所提出的问题。答案并不能解释为什么Mongoose决定要求开发人员同时提供模式和模型变量。django是一个框架的示例,在这个框架中,开发人员不再需要定义数据模式——开发人员将其模型写入models.py文件,并将其留给框架来管理模式。考虑到我使用django的经验,我想到的第一个原因是易于使用。也许更重要的是DRY(不要重复你自己)原则——当你改变模型时,你不必记得更新模式——django会帮你做的!Rails还为您管理数据的模式——开发人员不直接编辑模式,而是通过定义操作模式的迁移来更改模式 我可以理解的一个原因是Mongoose会将模式和模型分开,即您希望从两个模式构建模型的实例。这种情况可能会带来更大的复杂性
const tourSchema = new mongoose.Schema({
name: {
type: String,
required: [true, 'A tour must have a name'],
unique: true,
},
rating: {
type: Number,
default: 4.5,
},
price: {
type: Number,
required: [true, 'A tour must have a price'],
},
});
//tour model
const Tour = mongoose.model('Tour', tourSchema);
const testTour = new Tour({ // instance of our model
name: 'The Forest Hiker',
rating: 4.7,
price: 497,
});
// saving testTour document into database
testTour
.save()
.then((doc) => {
console.log(doc);
})
.catch((err) => {
console.log(err);
});