为什么猫鼬同时具有模式和模型? [英] Why does Mongoose have both schemas and models?

查看:50
本文介绍了为什么猫鼬同时具有模式和模型?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这两种类型的对象似乎彼此非常接近,以至于两者都有多余的感觉.拥有两种模式和模型有什么意义?

The two types of objects seem to be so close to one another that having both feels redundant. What is the point of having both schemas and models?

推荐答案

回答此类问题的最简单方法通常是举一个例子.在这种情况下,某人已经为我完成了:)

Often the easiest way to answer this type of question is with an example. In this case, someone has already done it for me :)

在这里看看:

http://rawberg.com/blog/nodejs/mongoose-orm -nested-models/

编辑:原始帖子(如评论中所述)似乎已不存在,所以我在下面进行复制.如果它返回了,或者它刚刚移动了,请告诉我.

The original post (as mentioned in the comments) seems to no longer exist, so I am reproducing it below. Should it ever return, or if it has just moved, please let me know.

它很好地描述了在猫鼬模型中使用架构的原因,以及为什么要这么做,并向您展示了如何在架构涉及结构等的同时通过模型推送任务.

It gives a decent description of using schemas within models in mongoose and why you would want to do it, and also shows you how to push tasks via the model while the schema is all about the structure etc.

原始帖子:

让我们从一个将模式嵌入模型中的简单示例开始.

Let’s start with a simple example of embedding a schema inside a model.

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 虚拟属性以方便地组合任务的名称和优先级.我在这里只指定了一个吸气剂,但也支持虚拟的吸气剂.

I created a new TaskSchema object with basic info a task might have. A Mongoose virtual attribute is setup to conveniently combine the name and priority of the Task. I only specified a getter here but virtual setters are supported as well.

我还定义了一个名为isHighPriority的简单任务方法,以演示方法如何在此设置下工作.

I also defined a simple task method called isHighPriority to demonstrate how methods work with this setup.

ListSchema定义中,您会注意到如何配置task键以容纳TaskSchema个对象的数组.任务密钥将成为 DocumentArray 提供了处理嵌入式Mongo文档的特殊方法.

In the ListSchema definition you’ll notice how the tasks key is configured to hold an array of TaskSchema objects. The task key will become an instance of DocumentArray which provides special methods for dealing with embedded Mongo documents.

现在,我只将ListSchema对象传递到mongoose.model中,而省略了TaskSchema.从技术上讲,不必将TaskSchema转换为正式模型,因为我们不会将其保存在自己的收藏夹中.稍后,我将向您展示它对您没有任何危害,并且可以帮助您以相同的方式组织所有模型,尤其是当它们开始跨越多个文件时.

For now I only passed the ListSchema object into mongoose.model and left the TaskSchema out. Technically it's not necessary to turn the TaskSchema into a formal model since we won’t be saving it in it’s own collection. Later on I’ll show you how it doesn’t harm anything if you do and it can help to organize all your models in the same way especially when they start spanning multiple files.

通过List模型设置,我们可以向其中添加一些任务并将其保存到Mongo.

With the List model setup let’s add a couple tasks to it and save them to 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对象添加的.这是一个细微的区别,可能并不立即直观.

The tasks attribute on the instance of our List model (simpleList) works like a regular JavaScript array and we can add new tasks to it using push. The important thing to notice is the tasks are added as regular JavaScript objects. It’s a subtle distinction that may not be immediately intuitive.

您可以从Mongo Shell中验证新列表和任务是否已保存到mongo.

You can verify from the Mongo shell that the new list and tasks were saved to 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并遍历其任务.

Now we can use the ObjectId to pull up the Sample List and iterate through its tasks.

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中,您无法直接访问嵌入式架构上的方法.在向猫鼬Google小组提出问题后,有一个公开票证对其进行了修复.发布了一个目前有用的解决方法.

If you run that last bit of code you’ll get an error saying the embedded document doesn’t have a method isHighPriority. In the current version of Mongoose you can’t access methods on embedded schemas directly. There’s an open ticket to fix it and after posing the question to the Mongoose Google Group, manimal45 posted a helpful work-around to use for now.

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));
    });
});

如果运行该代码,则应该在命令行上看到以下输出.

If you run that code you should see the following output on the command line.

Sample List retrieved
task one
task one (1)
true
task two
task two (5)
false

牢记这一解决方法,让我们将TaskSchema变成猫鼬模型.

With that work-around in mind let’s turn the TaskSchema into a Mongoose model.

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对象.

The TaskSchema definition is the same as before so I left it out. Once its turned into a model we can still access it’s underlying Schema object using dot notation.

让我们创建一个新列表并将两个Task模型实例嵌入其中.

Let’s create a new list and embed two Task model instances within it.

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模型实例嵌入到列表中时,我们在它们上调用toObject,以将其数据转换为List.tasks DocumentArray期望的普通JavaScript对象.当您以这种方式保存模型实例时,嵌入式文档将包含ObjectIds.

As we’re embedding the Task model instances into the List we’re calling toObject on them to convert their data into plain JavaScript objects that the List.tasks DocumentArray is expecting. When you save model instances this way your embedded documents will contain ObjectIds.

完整的代码示例为可用作要旨.希望随着猫鼬的不断发展,这些变通办法可以使事情顺利进行.我对Mongoose和MongoDB还是很陌生,所以请随时在评论中分享更好的解决方案和技巧.快乐的数据建模!

The complete code example is available as a gist. Hopefully these work-arounds help smooth things over as Mongoose continues to develop. I’m still pretty new to Mongoose and MongoDB so please feel free to share better solutions and tips in the comments. Happy data modeling!

这篇关于为什么猫鼬同时具有模式和模型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆