Die beiden Arten von Objekten scheinen so nahe beieinander zu liegen, dass es sich überflüssig anfühlt, beide zu haben. Was bringt es , sowohl Schemata als auch Modelle zu haben?
Die beiden Arten von Objekten scheinen so nahe beieinander zu liegen, dass es sich überflüssig anfühlt, beide zu haben. Was bringt es , sowohl Schemata als auch Modelle zu haben?
Antworten:
Der einfachste Weg, diese Art von Frage zu beantworten, ist oft ein Beispiel. In diesem Fall hat es schon jemand für mich gemacht :)
Schauen Sie hier:
http://rawberg.com/blog/nodejs/mongoose-orm-nested-models/
BEARBEITEN: Der ursprüngliche Beitrag (wie in den Kommentaren erwähnt) scheint nicht mehr zu existieren, daher reproduziere ich ihn unten. Sollte es jemals zurückkehren oder wenn es gerade umgezogen ist, lassen Sie es mich bitte wissen.
Es enthält eine anständige Beschreibung der Verwendung von Schemas in Modellen in Mungo und warum Sie dies tun möchten, und zeigt Ihnen auch, wie Sie Aufgaben über das Modell übertragen, während sich das Schema ausschließlich um die Struktur usw. dreht.
Ursprünglicher Beitrag:
Beginnen wir mit einem einfachen Beispiel für das Einbetten eines Schemas in ein Modell.
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'});
Ich habe ein neues TaskSchema
Objekt mit grundlegenden Informationen für eine Aufgabe erstellt. Ein virtuelles Mungoattribut wird eingerichtet, um den Namen und die Priorität der Aufgabe bequem zu kombinieren. Ich habe hier nur einen Getter angegeben, aber auch virtuelle Setter werden unterstützt.
Ich habe auch eine einfache Task-Methode definiert, um isHighPriority
zu demonstrieren, wie Methoden mit diesem Setup funktionieren.
In der ListSchema
Definition werden Sie feststellen, wie der Aufgabenschlüssel für ein Array von TaskSchema
Objekten konfiguriert ist . Der Aufgabenschlüssel wird zu einer Instanz, DocumentArray
die spezielle Methoden für den Umgang mit eingebetteten Mongo-Dokumenten bereitstellt.
Im ListSchema
Moment habe ich das Objekt nur an mongoose.model übergeben und das TaskSchema weggelassen. Technisch ist es nicht notwendig, das TaskSchema
in ein formales Modell umzuwandeln, da wir es nicht in einer eigenen Sammlung speichern werden. Später werde ich Ihnen zeigen, wie es nichts schadet, wenn Sie dies tun, und es kann hilfreich sein, alle Ihre Modelle auf die gleiche Weise zu organisieren, insbesondere wenn sie sich über mehrere Dateien erstrecken.
Mit dem List
Modell-Setup fügen wir ein paar Aufgaben hinzu und speichern sie 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');
}
});
Das Task-Attribut auf der Instanz unseres List
Modells ( simpleList
) funktioniert wie ein reguläres JavaScript-Array, und wir können ihm mithilfe von Push neue Aufgaben hinzufügen. Wichtig ist, dass die Aufgaben als reguläre JavaScript-Objekte hinzugefügt werden. Es ist eine subtile Unterscheidung, die möglicherweise nicht sofort intuitiv ist.
Sie können anhand der Mongo-Shell überprüfen, ob die neue Liste und die neuen Aufgaben in Mongo gespeichert wurden.
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" }
Jetzt können wir das verwenden ObjectId
, um das Sample List
aufzurufen und seine Aufgaben zu durchlaufen.
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());
});
});
Wenn Sie das letzte Codebit ausführen, wird eine Fehlermeldung angezeigt, dass das eingebettete Dokument keine Methode hat isHighPriority
. In der aktuellen Version von Mongoose können Sie nicht direkt auf Methoden in eingebetteten Schemas zugreifen. Es gibt ein offenes Ticket , um das Problem zu beheben. Nachdem man die Frage an die Mongoose Google Group gestellt hat, hat manimal45 eine hilfreiche Problemumgehung veröffentlicht, die vorerst verwendet werden kann.
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));
});
});
Wenn Sie diesen Code ausführen, sollte die folgende Ausgabe in der Befehlszeile angezeigt werden.
Sample List retrieved
task one
task one (1)
true
task two
task two (5)
false
Lassen Sie uns das TaskSchema
in ein Mungo-Modell verwandeln .
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');
Die TaskSchema
Definition ist die gleiche wie zuvor, also habe ich sie weggelassen. Sobald es in ein Modell umgewandelt wurde, können wir weiterhin mit der Punktnotation auf das zugrunde liegende Schemaobjekt zugreifen.
Lassen Sie uns eine neue Liste erstellen und zwei Taskmodellinstanzen darin einbetten.
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');
}
});
Während wir die Instanzen des Task-Modells in die Liste einbetten, fordern wir toObject
sie auf, ihre Daten in einfache JavaScript-Objekte zu konvertieren, die List.tasks
DocumentArray
das erwartet. Wenn Sie Modellinstanzen auf diese Weise speichern, enthalten Ihre eingebetteten Dokumente ObjectIds
.
Das vollständige Codebeispiel ist als Kern verfügbar . Hoffentlich helfen diese Workarounds dabei, die Dinge zu glätten, während sich Mongoose weiterentwickelt. Ich bin noch ziemlich neu in Mongoose und MongoDB, also zögern Sie nicht, bessere Lösungen und Tipps in den Kommentaren zu teilen. Viel Spaß beim Modellieren!
Schema ist ein Objekt, das die Struktur aller Dokumente definiert, die in Ihrer MongoDB-Sammlung gespeichert werden. Hier können Sie Typen und Validatoren für alle Ihre Datenelemente definieren.
Modell ist ein Objekt, mit dem Sie einfach auf eine benannte Sammlung zugreifen können. So können Sie die Sammlung abfragen und mithilfe des Schemas alle Dokumente validieren, die Sie in dieser Sammlung speichern. Es wird durch Kombinieren eines Schemas, einer Verbindung und eines Sammlungsnamens erstellt.
Ursprünglich formuliert von Valeri Karpov, MongoDB Blog
Ich glaube nicht, dass die akzeptierte Antwort tatsächlich die gestellte Frage beantwortet. Die Antwort erklärt nicht, warum Mongoose beschlossen hat, von einem Entwickler die Bereitstellung eines Schemas und einer Modellvariablen zu verlangen. Ein Beispiel für ein Framework, bei dem der Entwickler nicht mehr benötigt wirdDas Datenschema zu definieren ist django - ein Entwickler schreibt seine Modelle in die Datei models.py und überlässt sie dem Framework, um das Schema zu verwalten. Der erste Grund, warum ich dies aufgrund meiner Erfahrung mit Django tue, ist die Benutzerfreundlichkeit. Vielleicht noch wichtiger ist das DRY-Prinzip (wiederholen Sie sich nicht) - Sie müssen nicht daran denken, das Schema zu aktualisieren, wenn Sie das Modell ändern - django wird es für Sie tun! Rails verwaltet auch das Schema der Daten für Sie - ein Entwickler bearbeitet das Schema nicht direkt, sondern ändert es, indem er Migrationen definiert, die das Schema bearbeiten.
Ein Grund, warum ich verstehen konnte, dass Mongoose das Schema und das Modell trennen würde, sind Fälle, in denen Sie ein Modell aus zwei Schemata erstellen möchten. Ein solches Szenario kann zu mehr Komplexität führen, als es sich lohnt, es zu verwalten. Wenn Sie zwei Schemas haben, die von einem Modell verwaltet werden, warum sind sie dann nicht ein Schema?
Vielleicht ist die ursprüngliche Frage eher ein Relikt des traditionellen relationalen Datenbanksystems. In der Welt NoSQL / Mongo ist das Schema möglicherweise etwas flexibler als MySQL / PostgreSQL, und daher ist das Ändern des Schemas üblicher.
Um zu verstehen warum? Sie müssen verstehen, was eigentlich Mungo ist?
Nun, der Mungo ist eine Objektdatenmodellierungsbibliothek für MongoDB und Node JS, die eine höhere Abstraktionsebene bietet. Es ist also ein bisschen wie die Beziehung zwischen Express und Node, also ist Express eine Abstraktionsebene über dem regulären Node, während Mongoose eine Abstraktionsebene über dem regulären MongoDB-Treiber ist.
Eine Objektdatenmodellierungsbibliothek ist für uns nur eine Möglichkeit, Javascript-Code zu schreiben, der dann mit einer Datenbank interagiert. Wir könnten also einfach einen normalen MongoDB-Treiber verwenden, um auf unsere Datenbank zuzugreifen. Das würde gut funktionieren.
Stattdessen verwenden wir Mongoose, weil es uns sofort viel mehr Funktionen bietet und eine schnellere und einfachere Entwicklung unserer Anwendungen ermöglicht.
Einige der Funktionen von Mongoose bieten uns Schemata zur Modellierung unserer Daten und Beziehungen, eine einfache Datenvalidierung, eine einfache Abfrage-API, Middleware und vieles mehr.
In Mongoose modellieren wir in einem Schema unsere Daten, beschreiben die Struktur der Daten, die Standardwerte und die Validierung. Dann nehmen wir dieses Schema und erstellen daraus ein Modell. Ein Modell ist im Grunde ein Wrapper um das Schema. Dadurch können wir tatsächlich eine Schnittstelle zur Datenbank herstellen, um Dokumente zu erstellen, zu löschen, zu aktualisieren und zu lesen.
Lassen Sie uns ein Modell aus einem Schema erstellen.
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);
Nach Einberufung muss der erste Buchstabe eines Modellnamens groß geschrieben werden.
Lassen Sie uns eine Instanz unseres Modells erstellen, das wir mit Mungo und Schema erstellt haben. Interagiere auch mit unserer Datenbank.
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);
});
Schama und Modle Mungo zu haben, erleichtert uns das Leben.