I due tipi di oggetti sembrano essere così vicini l'uno all'altro che averli entrambi sembra ridondante. Qual è il punto di avere sia schemi che modelli?
I due tipi di oggetti sembrano essere così vicini l'uno all'altro che averli entrambi sembra ridondante. Qual è il punto di avere sia schemi che modelli?
Risposte:
Spesso il modo più semplice per rispondere a questo tipo di domanda è con un esempio. In questo caso qualcuno l'ha già fatto per me :)
Dai un'occhiata qui:
http://rawberg.com/blog/nodejs/mongoose-orm-nested-models/
EDIT: Il post originale (come menzionato nei commenti) sembra non esistere più, quindi lo sto riproducendo di seguito. Se dovesse mai tornare, o se si è appena spostato, fammelo sapere.
Fornisce una descrizione decente dell'uso degli schemi all'interno dei modelli in mangusta e del motivo per cui vorresti farlo, e mostra anche come spingere le attività tramite il modello mentre lo schema riguarda la struttura ecc.
Post originale:
Cominciamo con un semplice esempio di incorporamento di uno schema all'interno di un modello.
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'});
Ho creato un nuovo TaskSchema
oggetto con informazioni di base che potrebbe avere un'attività. Un attributo virtuale Mongoose è configurato per combinare convenientemente il nome e la priorità dell'attività. Ho solo specificato un getter qui, ma sono supportati anche i setter virtuali.
Ho anche definito un semplice metodo di attività chiamato isHighPriority
per dimostrare come i metodi funzionano con questa configurazione.
Nella ListSchema
definizione noterai come la chiave delle attività è configurata per contenere un array di TaskSchema
oggetti. La chiave dell'attività diventerà un'istanza della DocumentArray
quale fornisce metodi speciali per gestire i documenti Mongo incorporati.
Per ora ho passato l' ListSchema
oggetto solo a mongoose.model e ho lasciato fuori TaskSchema. Tecnicamente non è necessario trasformarlo TaskSchema
in un modello formale poiché non lo salveremo nella sua collezione. Più avanti ti mostrerò come non danneggia nulla se lo fai e può aiutarti a organizzare tutti i tuoi modelli allo stesso modo, specialmente quando iniziano a occupare più file.
Con la List
configurazione del modello aggiungiamo un paio di attività e le salviamo 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');
}
});
L'attributo tasks sull'istanza del nostro List
model ( simpleList
) funziona come un normale array JavaScript e possiamo aggiungervi nuove attività usando push. La cosa importante da notare è che le attività vengono aggiunte come normali oggetti JavaScript. È una sottile distinzione che potrebbe non essere immediatamente intuitiva.
È possibile verificare dalla shell Mongo che il nuovo elenco e le nuove attività siano stati salvati in 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" }
Ora possiamo usare ObjectId
per richiamare Sample List
e iterare attraverso i suoi compiti.
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());
});
});
Se esegui l'ultimo bit di codice riceverai un errore che dice che il documento incorporato non ha un metodo isHighPriority
. Nella versione corrente di Mongoose non è possibile accedere direttamente ai metodi sugli schemi incorporati. C'è un ticket aperto per risolverlo e dopo aver posto la domanda al Mongoose Google Group, manimal45 ha pubblicato un'utile soluzione da utilizzare per ora.
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));
});
});
Se esegui quel codice dovresti vedere il seguente output sulla riga di comando.
Sample List retrieved
task one
task one (1)
true
task two
task two (5)
false
Con questa soluzione in mente, trasformiamo il TaskSchema
in un modello 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');
La TaskSchema
definizione è la stessa di prima, quindi l'ho lasciata fuori. Una volta trasformato in un modello, possiamo ancora accedere all'oggetto Schema sottostante usando la notazione a punti.
Creiamo un nuovo elenco e incorporiamo due istanze del modello di attività al suo interno.
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');
}
});
Poiché stiamo incorporando le istanze del modello Task nella List, le chiediamo toObject
di convertire i loro dati in semplici oggetti JavaScript che List.tasks
DocumentArray
si aspettano. Quando salvi le istanze del modello in questo modo, i tuoi documenti incorporati conterranno ObjectIds
.
L'esempio di codice completo è disponibile come sintesi . Si spera che questi work-around aiutino a smussare le cose mentre Mongoose continua a svilupparsi. Sono ancora abbastanza nuovo per Mongoose e MongoDB, quindi sentiti libero di condividere soluzioni e suggerimenti migliori nei commenti. Buona modellazione dei dati!
Lo schema è un oggetto che definisce la struttura di tutti i documenti che verranno archiviati nella raccolta MongoDB; ti consente di definire tipi e validatori per tutti i tuoi elementi di dati.
Il modello è un oggetto che offre un facile accesso a una raccolta denominata, consentendo di interrogare la raccolta e utilizzare lo schema per convalidare i documenti salvati in quella raccolta. Viene creato combinando uno schema, una connessione e un nome di raccolta.
Originariamente formulato da Valeri Karpov, MongoDB Blog
Non credo che la risposta accettata risponda effettivamente alla domanda che è stata posta. La risposta non spiega perché Mongoose ha deciso di richiedere a uno sviluppatore di fornire sia una variabile Schema che una variabile Model. Un esempio di framework in cui hanno eliminato la necessità dello sviluppatoreper definire lo schema dei dati è django: uno sviluppatore scrive i propri modelli nel file models.py e lascia che sia il framework a gestire lo schema. La prima ragione che mi viene in mente per cui lo fanno, data la mia esperienza con django, è la facilità d'uso. Forse la cosa più importante è il principio DRY (non ripetere te stesso) - non devi ricordarti di aggiornare lo schema quando cambi il modello - django lo farà per te! Rails gestisce anche lo schema dei dati per te: uno sviluppatore non modifica direttamente lo schema, ma lo modifica definendo migrazioni che manipolano lo schema.
Un motivo per cui ho potuto capire che Mongoose separerebbe lo schema e il modello sono i casi in cui vorresti costruire un modello da due schemi. Un tale scenario potrebbe introdurre una complessità maggiore di quella che vale la pena gestire: se si hanno due schemi gestiti da un modello, perché non sono uno schema?
Forse la domanda originale è più una reliquia del tradizionale sistema di database relazionali. Nel mondo NoSQL / Mongo, forse lo schema è un po 'più flessibile di MySQL / PostgreSQL, e quindi cambiare lo schema è una pratica più comune.
Per capire perché? devi capire cos'è veramente la mangusta?
Bene, la mangusta è una libreria di modellazione dei dati a oggetti per MongoDB e Node JS, che fornisce un livello più alto di astrazione. Quindi è un po 'come la relazione tra Express e Node, quindi Express è uno strato di astrazione sul normale Node, mentre Mongoose è uno strato di astrazione sul normale driver MongoDB.
Una libreria di modellazione dati a oggetti è solo un modo per noi di scrivere codice Javascript che interagirà poi con un database. Quindi potremmo usare un normale driver MongoDB per accedere al nostro database, funzionerebbe perfettamente.
Ma invece usiamo Mongoose perché ci offre molte più funzionalità pronte all'uso, consentendo uno sviluppo più rapido e semplice delle nostre applicazioni.
Quindi, alcune delle funzionalità che Mongoose ci offre gli schemi per modellare i nostri dati e le nostre relazioni, una facile convalida dei dati, una semplice API di query, middleware e molto altro.
In Mongoose, uno schema è il luogo in cui modelliamo i nostri dati, dove descriviamo la struttura dei dati, i valori predefiniti e la convalida, quindi prendiamo quello schema e ne creiamo un modello, un modello è fondamentalmente un involucro dello schema, che ci consente di interfacciarci effettivamente con il database per creare, eliminare, aggiornare e leggere documenti.
Creiamo un modello da uno schema.
const tourSchema = new mongoose.Schema({
name: {
type: String,
required: [true, 'A tour must have a name'],
unique: true,
},
rating: {
type: Number,
default: 4.5,
},
price: {
type: Number,
required: [true, 'A tour must have a price'],
},
});
//tour model
const Tour = mongoose.model('Tour', tourSchema);
Secondo la convinzione, la prima lettera del nome di un modello deve essere in maiuscolo.
Creiamo un'istanza del nostro modello che abbiamo creato usando mangusta e schema. inoltre, interagisci con il nostro database.
const testTour = new Tour({ // instance of our model
name: 'The Forest Hiker',
rating: 4.7,
price: 497,
});
// saving testTour document into database
testTour
.save()
.then((doc) => {
console.log(doc);
})
.catch((err) => {
console.log(err);
});
Quindi avere sia schama che modle mongoose ci rende la vita più facile.