sql >> Database >  >> NoSQL >> MongoDB

Waarom heeft Mongoose zowel schema's als modellen?

BEWERKEN: Hoewel dit voor veel mensen nuttig was, beantwoordt het, zoals vermeld in de opmerkingen, het "hoe" in plaats van het waarom. Gelukkig is het waarom van de vraag ook elders beantwoord, met dit antwoord op een andere vraag. Dit staat al een tijdje in de reacties, maar ik realiseer me dat velen misschien niet zo ver komen bij het lezen.

Vaak is de eenvoudigste manier om dit soort vragen te beantwoorden met een voorbeeld. In dit geval heeft iemand het al voor mij gedaan :)

Kijk hier eens:

http://rawberg.com/blog/nodejs/mongoose-orm-nested-models/

BEWERKEN: Het originele bericht (zoals vermeld in de opmerkingen) lijkt niet meer te bestaan, dus ik reproduceer het hieronder. Mocht het ooit terugkomen, of als het net is verhuisd, laat het me dan weten.

Het geeft een behoorlijke beschrijving van het gebruik van schema's binnen modellen in mangoest en waarom je het zou willen doen, en laat je ook zien hoe je taken via het model kunt pushen terwijl het schema draait om de structuur enz.

Originele post:

Laten we beginnen met een eenvoudig voorbeeld van het insluiten van een schema in een 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'});

Ik heb een nieuw TaskSchema gemaakt object met basisinformatie die een taak zou kunnen hebben. Een virtueel kenmerk van Mongoose is ingesteld om de naam en prioriteit van de taak gemakkelijk te combineren. Ik heb hier alleen een getter gespecificeerd, maar virtuele setters worden ook ondersteund.

Ik definieerde ook een eenvoudige taakmethode genaamd isHighPriority om te demonstreren hoe methoden werken met deze opstelling.

In het ListSchema definitie zult u merken hoe de tasks sleutel is geconfigureerd voor een array van TaskSchema voorwerpen. De task key wordt een instantie van DocumentArray die speciale methoden biedt voor het omgaan met ingesloten Mongo-documenten.

Voorlopig ben ik alleen geslaagd voor de ListSchema object in mongoose.model en verliet het TaskSchema uit. Technisch gezien is het niet nodig om het TaskSchema in een formeel model omdat we het niet in zijn eigen collectie zullen opslaan. Later zal ik je laten zien hoe het geen kwaad kan als je dat doet en het kan helpen om al je modellen op dezelfde manier te ordenen, vooral wanneer ze meerdere bestanden beginnen te overspannen.

Met de List model setup laten we er een paar taken aan toevoegen en ze opslaan in 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'); 
    }
});

Het takenkenmerk op de instantie van onze List model (sampleList ) werkt als een gewone JavaScript-array en we kunnen er nieuwe taken aan toevoegen met push. Het belangrijkste om op te merken zijn de tasks worden toegevoegd als normale JavaScript-objecten. Het is een subtiel onderscheid dat misschien niet meteen intuïtief is.

U kunt vanuit de Mongo-shell verifiëren dat de nieuwe lijst en taken in mongo zijn opgeslagen.

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 kunnen we de ObjectId . gebruiken om de Sample List op te halen en herhaal zijn taken.

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());
    });
});

Als je dat laatste stukje code uitvoert, krijg je een foutmelding dat het ingesloten document geen methode heeft isHighPriority . In de huidige versie van Mongoose heb je geen directe toegang tot methoden op ingesloten schema's. Er is een open ticket om het te repareren en na de vraag aan de Mongoose Google Group te hebben gesteld, plaatste manimal45 een handige oplossing om voorlopig te gebruiken.

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));
    });
});

Als je die code uitvoert, zou je de volgende uitvoer op de opdrachtregel moeten zien.

Sample List retrieved
task one
task one (1)
true
task two
task two (5)
false

Laten we, met die tijdelijke oplossing in gedachten, het TaskSchema . omdraaien in een 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');

Het TaskSchema definitie is hetzelfde als voorheen, dus ik heb het weggelaten. Als het eenmaal in een model is veranderd, hebben we nog steeds toegang tot het onderliggende Schema-object met behulp van puntnotatie.

Laten we een nieuwe lijst maken en er twee instanties van het Taakmodel in insluiten.

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'); 
    }
});

Terwijl we de Taakmodelinstanties in de lijst insluiten, noemen we toObject op hen om hun gegevens om te zetten in eenvoudige JavaScript-objecten die de List.tasks DocumentArray verwacht. Als u modelinstanties op deze manier opslaat, bevatten uw ingesloten documenten ObjectIds .

Het volledige codevoorbeeld is beschikbaar als een kern. Hopelijk helpen deze tijdelijke oplossingen om de zaken glad te strijken terwijl Mongoose zich blijft ontwikkelen. Ik ben nog vrij nieuw voor Mongoose en MongoDB, dus deel gerust betere oplossingen en tips in de reacties. Veel plezier met datamodellering!



  1. MongoDB $min Aggregation Pipeline Operator

  2. Laravel - Taken in volgorde uitvoeren

  3. Draait mongodb?

  4. Omgaan met schemawijzigingen in Mongoose