为什么 Mongoose 既有模式又有模型? [英] Why does Mongoose have both schemas and models?

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

问题描述

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

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?

推荐答案

虽然这对很多人有用,但正如评论中提到的,它回答了如何"而不是为什么.值得庆幸的是,这个问题的原因也在别处得到了回答,另一个问题的答案.这在评论中已经有一段时间了,但我意识到很多人在阅读时可能不会那么远.

Although this has been useful for many people, as mentioned in the comments it answers the "how" rather than the why. Thankfully, the why of the question has been answered elsewhere also, with this answer to another question. This has been linked in the comments for some time but I realise that many may not get that far when reading.

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

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.

它很好地描述了在 mongoose 中的模型中使用模式以及您为什么要这样做,还向您展示了如何通过模型推送任务,而模式则是关于结构等.

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

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 定义中,您会注意到 tasks 键是如何配置为保存一个 TaskSchema 对象数组的.task 键将成为 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 模型 (sampleList) 实例上的 tasks 属性就像一个常规的 JavaScript 数组,我们可以使用 push 向它添加新任务.需要注意的重要一点是 tasks 作为常规 JavaScript 对象添加.这是一个微妙的区别,可能不会立即直观.

The tasks attribute on the instance of our List model (sampleList) 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 中,您无法直接访问嵌入式架构上的方法.有一个开放票来修复它,在向猫鼬谷歌组提出问题后,manimal45 发布了一个有用的解决方法,现在可以使用.

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 转换为 Mongoose 模型.

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 模型实例嵌入到 List 中时,我们对它们调用 toObject 以将它们的数据转换为 List.tasks DocumentArray 正在等待.当您以这种方式保存模型实例时,您的嵌入文档将包含 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 的不断发展,这些变通办法有助于使事情变得顺利.我对 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!

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

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