РЕДАКТИРАНЕ: Въпреки че това е било полезно за много хора, както е споменато в коментарите, то отговаря на „как“, а не на защо. За щастие, защо на въпроса е отговорено и другаде, с този отговор на друг въпрос. Това е свързано в коментарите от известно време, но осъзнавам, че мнозина може да не стигнат толкова далеч, когато четат.
Често най-лесният начин да отговорите на този тип въпроси е с пример. В случая някой вече го е направил вместо мен :)
Разгледайте тук:
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 е настроен за удобно комбиниране на името и приоритета на задачата. Тук посочих само getter, но виртуалните сетери също се поддържат.
Дефинирах и прост метод за задача, наречен isHighPriority
за да демонстрирате как методите работят с тази настройка.
В ListSchema
дефиниция, ще забележите как tasks
ключът е конфигуриран да държи масив от TaskSchema
обекти. task
key ще стане екземпляр на 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
модел (sampleList
) работи като обикновен масив на JavaScript и можем да добавяме нови задачи към него с помощта на push. Важното, което трябва да забележите, са tasks
се добавят като обикновени 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 Group, 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.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 в списъка, ние извикваме toObject
върху тях, за да конвертирате данните си в обикновени JavaScript обекти, които List.tasks
DocumentArray
очаква. Когато запазите екземпляри на модела по този начин, вашите вградени документи ще съдържат ObjectIds
.
Пълният пример за код е достъпен като същност. Надяваме се, че тези решения ще помогнат за изглаждане на нещата, тъй като Mongoose продължава да се развива. Все още съм доста нов за Mongoose и MongoDB, така че не се колебайте да споделяте по-добри решения и съвети в коментарите. Приятно моделиране на данни!