Часто самый простой способ ответить на этот тип вопроса - это на примере.В этом случае кто-то уже сделал это для меня:)
Взгляните сюда:
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
в формальную модель, поскольку мы не будем сохранять ее в собственной коллекции.Позже я покажу вам, как это ничего не повредит, если вы это сделаете, и это может помочь организовать все ваши модели одинаково, особенно когда они начинают охватывать несколько файлов.
С моделью List
setup давайте добавим к нему пару задач и сохраним их в 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, поэтому, пожалуйста, не стесняйтесь делиться лучшими решениями и советами в комментариях.Удачного моделирования данных!