EDIT: Selvom dette har været nyttigt for mange mennesker, svarer det som nævnt i kommentarerne på "hvordan" snarere end hvorfor. Heldigvis er spørgsmålets hvorfor også blevet besvaret andre steder, med dette svar på et andet spørgsmål. Dette har været linket i kommentarerne i nogen tid, men jeg er klar over, at mange måske ikke kommer så langt, når de læser.
Ofte er den nemmeste måde at besvare denne type spørgsmål med et eksempel. I dette tilfælde har nogen allerede gjort det for mig :)
Tag et kig her:
http://rawberg.com/blog/nodejs/mongoose-orm-nested-models/
EDIT: Det originale indlæg (som nævnt i kommentarerne) lader til ikke længere at eksistere, så jeg gengiver det nedenfor. Skulle det nogensinde vende tilbage, eller hvis det lige er flyttet, så lad mig det vide.
Det giver en anstændig beskrivelse af brugen af skemaer i modeller i mongoose, og hvorfor du ønsker at gøre det, og viser dig også, hvordan du pusher opgaver via modellen, mens skemaet handler om strukturen osv.
Original post:
Lad os starte med et simpelt eksempel på indlejring af et skema i en model.
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'});
Jeg oprettede et nyt TaskSchema
objekt med grundlæggende oplysninger, som en opgave kan have. En virtuel Mongoose-attribut er konfigureret til bekvemt at kombinere opgavens navn og prioritet. Jeg har kun angivet en getter her, men virtuelle sættere understøttes også.
Jeg definerede også en simpel opgavemetode kaldet isHighPriority
for at demonstrere, hvordan metoder fungerer med denne opsætning.
I ListSchema
definition vil du bemærke, hvordan tasks
nøglen er konfigureret til at indeholde en række TaskSchema
genstande. task
nøgle bliver en forekomst af DocumentArray
som giver specielle metoder til håndtering af indlejrede Mongo-dokumenter.
Indtil videre har jeg kun bestået ListSchema
objekt til mongoose.model
og forlod TaskSchema
ud. Teknisk set er det ikke nødvendigt at vende TaskSchema
til en formel model, da vi ikke gemmer den i sin egen samling. Senere vil jeg vise dig, hvordan det ikke skader noget, hvis du gør det, og det kan hjælpe med at organisere alle dine modeller på samme måde, især når de begynder at spænde over flere filer.
Med List
modelopsætning lad os tilføje et par opgaver til det og gemme dem i 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');
}
});
Opgaveattributten på forekomsten af vores List
model (sampleList
) fungerer som et almindeligt JavaScript-array, og vi kan tilføje nye opgaver til det ved hjælp af push. Det vigtige at bemærke er tasks
tilføjes som almindelige JavaScript-objekter. Det er en subtil skelnen, som måske ikke umiddelbart er intuitiv.
Du kan bekræfte fra Mongo-skallen, at den nye liste og opgaver blev gemt på 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" }
Nu kan vi bruge ObjectId
for at trække Sample List
frem og gentage dens opgaver.
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());
});
});
Hvis du kører den sidste bit kode, får du en fejl, der siger, at det indlejrede dokument ikke har en metode isHighPriority
. I den nuværende version af Mongoose kan du ikke få direkte adgang til metoder på indlejrede skemaer. Der er en åben billet til at rette det, og efter at have stillet spørgsmålet til Mongoose Google-gruppen, postede manimal45 en nyttig løsning, der kan bruges indtil videre.
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));
});
});
Hvis du kører den kode, skulle du se følgende output på kommandolinjen.
Sample List retrieved
task one
task one (1)
true
task two
task two (5)
false
Med denne løsning i tankerne, lad os vende TaskSchema
ind i en 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');
TaskSchema
definition er den samme som før, så jeg udelod den. Når først det er blevet til en model, kan vi stadig få adgang til det underliggende Schema-objekt ved hjælp af punktnotation.
Lad os oprette en ny liste og integrere to opgavemodelforekomster i den.
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');
}
});
Mens vi indlejrer opgavemodelforekomsterne i listen, kalder vi toObject
på dem for at konvertere deres data til almindelige JavaScript-objekter, som List.tasks
DocumentArray
venter. Når du gemmer modelforekomster på denne måde, vil dine indlejrede dokumenter indeholde ObjectIds
.
Det komplette kodeeksempel er tilgængeligt som en essens. Forhåbentlig hjælper disse løsninger med at udjævne tingene, efterhånden som Mongoose fortsætter med at udvikle sig. Jeg er stadig ret ny til Mongoose og MongoDB, så du er velkommen til at dele bedre løsninger og tips i kommentarerne. Glad datamodellering!