Ada*_*ord 57
回答这类问题的最简单方法通常是举个例子.在这种情况下,有人已经为我做了:)
看看这里:
http://rawberg.com/blog/nodejs/mongoose-orm-nested-models/
编辑:原帖(如评论中所述)似乎不再存在,所以我在下面复制它.它是否应该返回,或者它刚刚移动,请告诉我.
它给出了在mongoose中使用模型中的模式的正确描述以及为什么要这样做,并且还向您展示了如何通过模型推送任务,而模式是关于结构等的.
原帖:
让我们从一个在模型中嵌入模式的简单示例开始.
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'});
Run Code Online (Sandbox Code Playgroud)
我创建了一个TaskSchema具有任务可能具有的基本信息的新对象.设置Mongoose 虚拟属性以方便地组合任务的名称和优先级.我这里只指定了一个getter,但也支持虚拟setter.
我还定义了一个简单的任务方法,isHighPriority用于演示方法如何使用此设置.
在ListSchema定义中,您将注意到任务键如何配置为保存TaskSchema对象数组.任务键将成为一个实例DocumentArray,提供处理嵌入式Mongo文档的特殊方法.
现在我只将ListSchema对象传递给mongoose.model并将TaskSchema保留了.从技术上讲,没有必要把它TaskSchema变成一个正式的模型,因为我们不会将它保存在它自己的集合中.稍后我将向您展示如果您这样做不会造成任何伤害,它可以帮助您以相同的方式组织所有模型,尤其是当它们开始跨越多个文件时.
使用List模型设置,让我们为它添加几个任务并将它们保存到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');
}
});
Run Code Online (Sandbox Code Playgroud)
我们的Listmodel(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" }
Run Code Online (Sandbox Code Playgroud)
现在我们可以使用它ObjectId来完成Sample List并迭代它的任务.
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());
});
});
Run Code Online (Sandbox Code Playgroud)
如果你运行最后一段代码,你会收到一个错误,说嵌入式文档没有方法isHighPriority.在当前版本的Mongoose中,您无法直接访问嵌入式架构上的方法.有一个公开的机票来解决它,在向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));
});
});
Run Code Online (Sandbox Code Playgroud)
如果您运行该代码,您应该在命令行上看到以下输出.
Sample List retrieved
task one
task one (1)
true
task two
task two (5)
false
Run Code Online (Sandbox Code Playgroud)
考虑到这种解决方法,让我们把它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');
Run Code Online (Sandbox Code Playgroud)
该TaskSchema定义是和以前一样,所以我离开了出来.一旦它变成模型,我们仍然可以使用点表示法访问它的底层Schema对象.
让我们创建一个新列表并在其中嵌入两个Task模型实例.
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');
}
});
Run Code Online (Sandbox Code Playgroud)
当我们将Task模型实例嵌入到List中时,我们正在调用toObject它们将它们的数据转换List.tasks DocumentArray为期望的纯JavaScript对象.以这种方式保存模型实例时,嵌入的文档将包含ObjectIds.
完整的代码示例作为要点提供.希望这些解决方案有助于在Mongoose继续发展的过程中顺利完成任务.我仍然是Mongoose和MongoDB的新手,所以请随时在评论中分享更好的解决方案和技巧.快乐的数据建模!
Zee*_*mon 50
Schema是一个对象,它定义将存储在MongoDB集合中的任何文档的结构; 它使您可以为所有数据项定义类型和验证器.
Model是一个对象,使您可以轻松访问命名集合,允许您查询集合并使用Schema验证保存到该集合的任何文档.它是通过组合Schema,Connection和集合名称创建的.
最初由MongoDB博客的 Valeri Karpov表达
我认为接受的答案实际上无法回答提出的问题。答案并不能解释为什么 Mongoose决定要求开发人员同时提供Schema和Model变量。他们消除了对开发人员的需求的框架示例定义数据模式的方式是django-开发人员在models.py文件中编写模型,然后将其留给框架来管理模式。考虑到我在django上的经验,想到它们为什么要这样做的第一个原因是易于使用。也许更重要的是DRY(不要重复自己)原理-更改模型时您不必记住要更新架构-django将为您做到!Rails还可以为您管理数据的架构-开发人员不会直接编辑架构,而是通过定义对架构进行的迁移来对其进行更改。
我能理解Mongoose会将架构和模型分开的一个原因是,您想从两个架构中构建模型的实例。这种情况可能会带来比值得管理的更为复杂的复杂性-如果您有两个由一个模型管理的模式,为什么它们不是一个模式?
最初的问题也许更多地是传统关系数据库系统的遗迹。在NoSQL / Mongo世界中,架构可能比MySQL / PostgreSQL灵活一些,因此更改架构是更常见的做法。
| 归档时间: |
|
| 查看次数: |
22236 次 |
| 最近记录: |