Почему у Mongoose есть схемы и модели? - PullRequest
85 голосов
/ 03 февраля 2012

Два типа объектов кажутся настолько близкими друг к другу, что оба они кажутся излишними.Какой смысл иметь и схемы и модели?

Ответы [ 4 ]

57 голосов
/ 03 февраля 2012

Часто самый простой способ ответить на этот тип вопроса - это на примере.В этом случае кто-то уже сделал это для меня:)

Взгляните сюда:

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

Я создал новый объект TaskSchema с базовой информацией, которую может иметь задача.Виртуальный атрибут Mongoose настроен так, чтобы удобно сочетать имя и приоритет Задачи.Я только указал здесь геттер, но также поддерживаются виртуальные сеттеры.

Я также определил простой метод задачи под названием isHighPriority, чтобы продемонстрировать, как методы работают с этой настройкой.

В ListSchema определение, вы заметите, как ключ задач настроен для хранения массива TaskSchema объектов.Ключ задачи станет экземпляром DocumentArray, который предоставляет специальные методы для работы со встроенными документами Mongo.

На данный момент я только передал объект ListSchema в mongoose.model и оставилTaskSchema вне.Технически нет необходимости превращать TaskSchema в формальную модель, поскольку мы не будем сохранять ее в собственной коллекции.Позже я покажу вам, как это ничего не повредит, если вы это сделаете, и это может помочь организовать все ваши модели одинаково, особенно когда они начинают охватывать несколько файлов.

С моделью Listsetup давайте добавим к нему пару задач и сохраним их в 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'); 
    }
});

Атрибут tasks в экземпляре нашей модели List (simpleList) работает как обычный массив JavaScript, и мы можем добавитьновые задачи к нему, используя толчок.Важно отметить, что задачи добавляются как обычные объекты JavaScript.Это тонкое различие, которое может быть не сразу интуитивно понятным.

Вы можете проверить из оболочки Mongo, что новый список и задачи были сохранены в 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 вы не можете напрямую обращаться к методам встроенных схем.Существует открытый тикет , чтобы исправить это, и после того, как он задал вопрос в Группе Google 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));
    });
});

Если вы запустите этот кодвы должны увидеть следующий вывод в командной строке.

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

Имея в виду этот обходной путь, давайте превратим 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');

* 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 в список, который мы им вызываем toObject, чтобы преобразовать их данные в простые объекты JavaScript, которых ожидает List.tasks DocumentArray.Когда вы сохраняете экземпляры модели таким образом, ваши встроенные документы будут содержать ObjectIds.

Полный пример кода доступен в виде сущности .Надеемся, что эти обходные пути помогут сгладить ситуацию, поскольку Mongoose продолжает развиваться.Я все еще довольно плохо знаком с Mongoose и MongoDB, поэтому, пожалуйста, не стесняйтесь делиться лучшими решениями и советами в комментариях.Удачного моделирования данных!

47 голосов
/ 16 марта 2016

Схема - это объект, который определяет структуру любых документов, которые будут храниться в вашей коллекции MongoDB; это позволяет вам определять типы и валидаторы для всех ваших элементов данных.

Модель - это объект, который предоставляет вам простой доступ к именованной коллекции, позволяя запрашивать коллекцию и использовать схему для проверки любых документов, сохраненных в этой коллекции. Он создается путем объединения схемы, соединения и имени коллекции.

Первоначально сформулировано Валерием Карповым, Блог MongoDB

3 голосов
/ 22 октября 2017

Я не думаю, что принятый ответ на самом деле отвечает на поставленный вопрос. Ответ не объясняет , почему Mongoose решила потребовать от разработчика предоставления как схемы, так и переменной модели. Примером фреймворка, в котором отпадает необходимость для разработчика определять схему данных, является django - разработчик записывает свои модели в файл models.py и оставляет его для управления фреймворком схема. Первая причина, которая приходит на ум, почему они делают это, учитывая мой опыт работы с django, это простота использования. Возможно, более важным является принцип «СУХОЙ» (не повторяйте себя) - вам не нужно обновлять схему при смене модели - django сделает это за вас! Rails также управляет схемой данных для вас - разработчик не редактирует схему напрямую, а изменяет ее, определяя миграции, которые манипулируют схемой.

Одной из причин, по которой я мог понять, что Mongoose будет отделять схему и модель, являются случаи, когда вы захотите построить модель из двух схем. Такой сценарий может привести к большей сложности, чем стоит управлять - если у вас есть две схемы, управляемые одной моделью, почему они не являются одной схемой?

Возможно, первоначальный вопрос - это скорее реликт традиционной системы реляционных баз данных. В мире NoSQL / Mongo, возможно, схема немного более гибкая, чем MySQL / PostgreSQL, и, таким образом, изменение схемы является более распространенной практикой.

1 голос
/ 14 января 2018

Проще говоря,

A модель - это модель объекта данных, как вы можете найти в шаблоне проектирования MVC. Она определяет Структура , какой тип данных должен храниться в базе данных и какой тип отношения данные имеют.

A схема похожа на database schema, определение того, что будет храниться в базе данных.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...