这两种类型的对象似乎彼此非常接近,以至于两者都显得多余。什么是具有点既架构和模式?
Answers:
回答此类问题的最简单方法通常是举一个例子。在这种情况下,某人已经为我完成了:)
在这里看看:
http://rawberg.com/blog/nodejs/mongoose-orm-nested-models/
编辑:原始帖子(如评论中所述)似乎不再存在,所以我在下面复制它。如果它返回了,或者它刚刚移动了,请告诉我。
它给出了在猫鼬模型中使用架构的恰当描述,以及您为什么要这样做,并向您展示了当架构涉及结构等时如何通过模型推送任务。
原始帖子:
让我们从将模式嵌入模型中的简单示例开始。
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
使用任务可能具有的基本信息创建了一个新对象。设置了猫鼬虚拟属性以方便地组合任务的名称和优先级。我在这里只指定了一个吸气剂,但也支持虚拟的吸气剂。
我还定义了一个简单的任务方法,isHighPriority
以演示方法如何在此设置下工作。
在ListSchema
定义中,您将注意到如何配置task键以容纳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');
}
});
List
模型(simpleList
)实例上的task属性的工作方式类似于常规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
来调出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());
});
});
如果运行最后的代码,您会得到一个错误消息,提示嵌入式文档没有方法isHighPriority
。在当前版本的Mongoose中,您不能直接访问嵌入式架构上的方法。有一张开放的票证可以解决它,向Mongoose Google Group提出问题后,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.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
定义是一样的,所以我离开它之前。将其转换为模型后,我们仍然可以使用点表示法访问其基础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');
}
});
当我们将Task模型实例嵌入到List中时,我们呼吁toObject
它们将其数据转换List.tasks
DocumentArray
为期望的普通JavaScript对象。以这种方式保存模型实例时,嵌入式文档将包含ObjectIds
。
完整的代码示例可作为参考。希望随着猫鼬的不断发展,这些变通办法可以使事情顺利进行。我对Mongoose和MongoDB还是很陌生,所以请随时在评论中分享更好的解决方案和技巧。快乐的数据建模!
模式是一个对象,用于定义将存储在MongoDB集合中的所有文档的结构;它使您能够为所有数据项定义类型和验证器。
模型是使您可以轻松访问命名集合的对象,允许您查询集合并使用Schema来验证保存到该集合的任何文档。它是通过组合架构,连接和集合名称来创建的。
最初由MongoDB博客的 Valeri Karpov表达
我认为接受的答案实际上无法回答提出的问题。答案并不能解释为什么 Mongoose决定要求开发人员同时提供Schema和Model变量。他们消除了对开发人员的需求的框架示例定义数据模式的方式是django-开发人员在models.py文件中编写模型,然后将其留给框架来管理模式。考虑到我在django上的经验,想到它们为什么要这样做的第一个原因是易于使用。也许更重要的是DRY(不要重复自己)原理-更改模型时您不必记住要更新架构-django将为您做到!Rails还可以为您管理数据的架构-开发人员不会直接编辑架构,而是通过定义对架构进行的迁移来对其进行更改。
我能理解Mongoose会将架构和模型分开的一个原因是,您想从两个架构中构建模型的实例。这种情况可能会带来比值得管理的更为复杂的复杂性-如果您有两个由一个模型管理的模式,为什么它们不是一个模式?
最初的问题也许更多地是传统关系数据库系统的遗迹。在NoSQL / Mongo世界中,架构可能比MySQL / PostgreSQL灵活一些,因此更改架构是更常见的做法。
明白为什么?您必须了解猫鼬到底是什么?
好吧,猫鼬是用于MongoDB和Node JS的对象数据建模库,提供了更高级别的抽象。因此,这有点像Express和Node之间的关系,因此Express是常规Node之上的抽象层,而Mongoose是常规MongoDB驱动程序之上的抽象层。
对象数据建模库只是我们编写Javascript代码的一种方法,然后将其与数据库进行交互。因此,我们可以只使用常规的MongoDB驱动程序来访问数据库,就可以了。
但是我们改用Mongoose,因为它为我们提供了更多的即用型功能,从而可以更快,更简单地开发应用程序。
因此,Mongoose的一些功能为我们提供了用于对数据和关系进行建模的模式,轻松的数据验证,简单的查询API,中间件等等。
在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);
});
因此,同时拥有schama和modle猫鼬会使我们的生活更轻松。