UPRAVIT: Ačkoli to bylo užitečné pro mnoho lidí, jak je uvedeno v komentářích, odpovídá to spíše „jak“ než proč. Naštěstí, proč byla otázka zodpovězena i jinde, touto odpovědí na jinou otázku. Toto bylo v komentářích již nějakou dobu odkazováno, ale uvědomuji si, že mnozí se při čtení nemusí dostat tak daleko.
Často je nejjednodušší odpovědět na tento typ otázek pomocí příkladu. V tomto případě to za mě už někdo udělal :)
Podívejte se sem:
http://rawberg.com/blog/nodejs/mongoose-orm-nested-models/
UPRAVIT: Zdá se, že původní příspěvek (jak je zmíněn v komentářích) již neexistuje, proto jej reprodukuji níže. Pokud by se někdy vrátila nebo se právě přesunula, dejte mi prosím vědět.
Poskytuje slušný popis použití schémat v modelech v mongoose a proč byste to chtěli udělat, a také vám ukazuje, jak předávat úkoly prostřednictvím modelu, zatímco schéma je o struktuře atd.
Původní příspěvek:
Začněme jednoduchým příkladem vložení schématu do modelu.
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'});
Vytvořil jsem nové TaskSchema
objekt se základními informacemi, které úkol může mít. Virtuální atribut Mongoose je nastaven tak, aby pohodlně kombinoval název a prioritu úkolu. Specifikoval jsem pouze getter zde, ale virtuální settery jsou také podporovány.
Také jsem definoval jednoduchou metodu úlohy nazvanou isHighPriority
demonstrovat, jak metody fungují s tímto nastavením.
V ListSchema
definice si všimnete, jak tasks
klíč je nakonfigurován tak, aby obsahoval pole TaskSchema
objektů. task
key se stane instancí DocumentArray
který poskytuje speciální metody pro práci s vloženými dokumenty Mongo.
Prozatím jsem prošel pouze ListSchema
objekt do mongoose.model
a opustili TaskSchema
ven. Technicky není nutné zapínat TaskSchema
do formálního modelu, protože jej nebudeme ukládat do jeho vlastní sbírky. Později vám ukážu, že pokud to uděláte, ničemu neublíží a že vám to pomůže uspořádat všechny vaše modely stejným způsobem, zvláště když začnou zahrnovat více souborů.
Pomocí List
nastavení modelu, přidejte k němu několik úkolů a uložte je do 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');
}
});
Atribut úkolů v instanci našeho List
model (sampleList
) funguje jako běžné pole JavaScriptu a můžeme do něj přidávat nové úkoly pomocí push. Důležitá věc, které je třeba si povšimnout, jsou tasks
jsou přidány jako běžné objekty JavaScriptu. Je to jemný rozdíl, který nemusí být hned intuitivní.
Z prostředí Mongo můžete ověřit, že nový seznam a úkoly byly uloženy do 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" }
Nyní můžeme použít ObjectId
vytáhněte Sample List
a procházet jeho úkoly.
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());
});
});
Pokud spustíte poslední část kódu, zobrazí se chyba, že vložený dokument nemá metodu isHighPriority
. V aktuální verzi Mongoose nemáte přímý přístup k metodám na vložených schématech. Existuje otevřený lístek, jak to opravit, a poté, co položil otázku skupině Mongoose Google, manimal45 zveřejnil užitečné řešení, které lze prozatím použít.
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));
});
});
Pokud tento kód spustíte, měli byste na příkazovém řádku vidět následující výstup.
Sample List retrieved
task one
task one (1)
true
task two
task two (5)
false
S ohledem na toto řešení pojďme změnit TaskSchema
do modelu 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');
TaskSchema
definice je stejná jako předtím, takže jsem ji vynechal. Jakmile se změní na model, stále máme přístup k základnímu objektu Schema pomocí tečkové notace.
Vytvořme nový seznam a vložíme do něj dvě instance modelu Task.
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');
}
});
Když vkládáme instance modelu úloh do seznamu, voláme toObject
na nich převést jejich data na prosté objekty JavaScript, které List.tasks
DocumentArray
očekává. Když uložíte instance modelu tímto způsobem, budou vaše vložené dokumenty obsahovat ObjectIds
.
Kompletní příklad kódu je k dispozici jako podstata. Doufejme, že tato řešení pomohou věci usnadnit, protože se Mongoose nadále vyvíjí. V Mongoose a MongoDB jsem stále docela nový, takže neváhejte a podělte se o lepší řešení a tipy v komentářích. Šťastné modelování dat!