sql >> Database teknologi >  >> NoSQL >> MongoDB

Hvorfor har Mongoose både skemaer og modeller?

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!



  1. håndtering af redis maxmemory situationer med rails ved brug af rails caching

  2. Formater et tal som valuta i SQL

  3. Få en tydelig aggregering af et matrixfelt på tværs af indekser

  4. hvordan håndterer man session expire ved at basere redis?