Эти два типа объектов кажутся настолько близкими друг к другу, что наличие обоих кажется излишним. Какой смысл иметь и схемы, и модели?
Эти два типа объектов кажутся настолько близкими друг к другу, что наличие обоих кажется излишним. Какой смысл иметь и схемы, и модели?
Ответы:
Часто самый простой способ ответить на этот вопрос - это привести пример. В данном случае кто-то уже сделал это за меня :)
Взгляните сюда:
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.
На данный момент я только передал 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');
}
});
Атрибут tasks в экземпляре нашей List
модели ( simpleList
) работает как обычный массив JavaScript, и мы можем добавлять в него новые задачи с помощью push. Важно отметить, что задачи добавляются как обычные объекты 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 вы не можете напрямую обращаться к методам встроенных схем. Есть открытый билет, чтобы исправить это, и, задав вопрос группе Mongoose Google, 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
Определение такое же , как и раньше , так что я оставил его. После того, как он превратился в модель, мы все еще можем получить доступ к его базовому объекту схемы, используя точечную нотацию.
Создадим новый список и встроим в него два экземпляра модели 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
их преобразовать их данные в простые объекты JavaScript, которые List.tasks
DocumentArray
ожидает. Когда вы сохраняете экземпляры модели таким образом, ваши встроенные документы будут содержать ObjectIds
.
Полный пример кода доступен как суть . Надеюсь, эти обходные пути помогут сгладить ситуацию, поскольку Mongoose продолжает развиваться. Я все еще новичок в Mongoose и MongoDB, поэтому не стесняйтесь делиться лучшими решениями и советами в комментариях. Удачного моделирования данных!
Схема - это объект, который определяет структуру любых документов, которые будут храниться в вашей коллекции MongoDB; он позволяет вам определять типы и валидаторы для всех ваших элементов данных.
Модель - это объект, который дает вам легкий доступ к именованной коллекции, позволяя вам запрашивать коллекцию и использовать схему для проверки любых документов, которые вы сохраняете в этой коллекции. Он создается путем объединения схемы, соединения и имени коллекции.
Первоначально сформулировано Валерием Карповым, блог MongoDB
Я не думаю, что принятый ответ действительно отвечает на поставленный вопрос. Ответ не объясняет, почему Mongoose решил потребовать от разработчика предоставить как схему, так и переменную модели. Пример фреймворка, где отпала необходимость в разработчикеДля определения схемы данных используется 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);
});
Таким образом, наличие шама и мангуста делает нашу жизнь проще.