Programing

Mongoose에 스키마와 모델이 모두있는 이유는 무엇입니까?

lottogame 2020. 9. 14. 21:38
반응형

Mongoose에 스키마와 모델이 모두있는 이유는 무엇입니까?


두 가지 유형의 객체는 서로 너무 가까워서 둘 다 중복 된 느낌을줍니다. 스키마와 모델 모두 갖는 이유는 무엇입니까 ?


종종 이러한 유형의 질문에 답하는 가장 쉬운 방법은 예를 사용하는 것입니다. 이 경우 누군가 이미 나를 위해 해주었습니다 :)

여기를보세요 :

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작업에있을 수있는 기본 정보 로 새 개체를 만들었습니다 . Mongoose 가상 속성 은 태스크의 이름과 우선 순위를 편리하게 결합하도록 설정됩니다. 여기에 게터 만 지정했지만 가상 세터도 지원됩니다.

또한 isHighPriority이 설정에서 메서드가 작동하는 방식을 보여주기 위해 호출되는 간단한 작업 메서드도 정의했습니다 .

에서 ListSchema정의 당신은 작업 키의 배열을 유지하도록 구성하는 방법을 알 수 있습니다 TaskSchema개체를. 태스크 키는 DocumentArray포함 된 Mongo 문서를 처리하기위한 특별한 방법을 제공 하는 인스턴스가 됩니다.

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.

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

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.

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" }

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

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

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

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.

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

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.

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!


Schema is an object that defines the structure of any documents that will be stored in your MongoDB collection; it enables you to define types and validators for all of your data items.

Model is an object that gives you easy access to a named collection, allowing you to query the collection and use the Schema to validate any documents you save to that collection. It is created by combining a Schema, a Connection, and a collection name.

Originally phrased by Valeri Karpov, MongoDB Blog


I don't think the accepted answer actually answers the question that was posed. The answer doesn't explain why Mongoose has decided to require a developer to provide both a Schema and a Model variable. An example of a framework where they have eliminated the need for the developer to define the data schema is django--a developer writes up their models in the models.py file, and leaves it to the framework to manage the schema. The first reason that comes to mind for why they do this, given my experience with django, is ease-of-use. Perhaps more importantly is the DRY (don't repeat yourself) principle--you don't have to remember to update the schema when you change the model--django will do it for you! Rails also manages the schema of the data for you--a developer doesn't edit the schema directly, but changes it by defining migrations that manipulate the schema.

One reason I could understand that Mongoose would separate the schema and the model is instances where you would want to build a model from two schemas. Such a scenario might introduce more complexity than is worth managing--if you have two schemas that are managed by one model, why aren't they one schema?

Perhaps the original question is more a relic of the traditional relational database system. In world NoSQL/Mongo world, perhaps the schema is a little more flexible than MySQL/PostgreSQL, and thus changing the schema is more common practice.


In simple words,

A model is a data object model, like you would find in an MVC design pattern.It defines Structure what kind of data has to be stored in a database and what type of relation the data has.

A schema is like a database schema, the definition of what will be stored in a database.

참고URL : https://stackoverflow.com/questions/9127174/why-does-mongoose-have-both-schemas-and-models

반응형