Отображение многих-ко-многим с помощью Mongoose
У меня есть FlashcardSchemas и PackageSchemas в моем дизайне. Одна флешка может принадлежать различным пакетам, а пакет может содержать различные карточки.
Ниже вы можете увидеть сокращенную версию моих определений схемы mongoose:
// package-schema.js
var Schema = mongoose.Schema,
ObjectId = Schema.ObjectId;
var PackageSchema = new Schema({
id : ObjectId,
title : { type: String, required: true },
flashcards : [ FlashcardSchema ]
});
var exports = module.exports = mongoose.model('Package', PackageSchema);
// flashcard-schema.js
var Schema = mongoose.Schema,
ObjectId = Schema.ObjectId;
var FlashcardSchema = new Schema({
id : ObjectId,
type : { type: String, default: '' },
story : { type: String, default: '' },
packages : [ PackageSchema ]
});
var exports = module.exports = mongoose.model('Flashcard', FlashcardSchema);
Как видно из комментариев выше, эти два определения схемы относятся к отдельным файлам и ссылаются друг на друга.
Я получаю исключение, заявляющее, что PackageSchema не определено, как и ожидалось. Как я могу сопоставить отношение "многие ко многим" с мангустом?
Ответы
Ответ 1
Вы делаете это правильно, однако проблема заключается в том, что вы должны включать PackageSchema в flashcard-schema.js и наоборот. В противном случае эти файлы не имеют представления о том, что вы ссылаетесь на
var Schema = mongoose.Schema,
ObjectId = Schema.ObjectId;
PackageSchema = require('./path/to/package-schema.js')
var FlashcardSchema = new Schema({
id : ObjectId,
type : { type: String, default: '' },
story : { type: String, default: '' },
packages : [ PackageSchema ]
});
Ответ 2
Я новичок в node, mongoDB и mongoose, но я думаю, что правильный способ сделать это:
var PackageSchema = new Schema({
id: ObjectId,
title: { type: String, required: true },
flashcards: [ {type : mongoose.Schema.ObjectId, ref : 'Flashcard'} ]
});
var FlashcardSchema = new Schema({
id: ObjectId,
type: { type: String, default: '' },
story: { type: String, default: '' },
packages: [ {type : mongoose.Schema.ObjectId, ref : 'Package'} ]
});
Таким образом, вы сохраняете только ссылку на объект, а не встроенный объект.
Ответ 3
Вы думаете об этом слишком сильно, как реляционный хранилище данных. Если это то, что вы хотите, используйте MySQL (или другую СУБД)
В противном случае можно использовать третью схему, но не забывайте, что это будет только идентификатор каждого объекта (нет объединений, помните), поэтому вам все равно придется извлекать каждый другой элемент в отдельный запрос.
Ответ 4
Вы можете использовать метод Schema.add(), чтобы избежать проблемы с прямой ссылкой.
Это (непроверенное) решение помещает схему в один .js файл
модели /index.js
var Schema = mongoose.Schema,
ObjectId = Schema.ObjectId;
// avoid forward referencing
var PackageSchema = new Schema();
var FlashcardSchema = new Schema();
PackageSchema.add({
id : ObjectId,
title : { type: String, required: true },
flashcards : [ FlashcardSchema ]
});
FlashcardSchema.add({
id : ObjectId,
type : { type: String, default: '' },
story : { type: String, default: '' },
packages : [ PackageSchema ]
});
// Exports both types
module.exports = {
Package: mongoose.model('Package', PackageSchema),
Flashcard: mongoose.model('Flashcard', FlashcardSchema)
};
Ответ 5
https://www.npmjs.com/package/mongoose-relationship
##Many-To-Many with Multiple paths
var mongoose = require("mongoose"),
Schema = mongoose.Schema,
relationship = require("mongoose-relationship");
var ParentSchema = new Schema({
children:[{ type:Schema.ObjectId, ref:"Child" }]
});
var Parent = mongoose.models("Parent", ParentSchema);
var OtherParentSchema = new Schema({
children:[{ type:Schema.ObjectId, ref:"Child" }]
});
var OtherParent = mongoose.models("OtherParent", OtherParentSchema);
var ChildSchema = new Schema({
parents: [{ type:Schema.ObjectId, ref:"Parent", childPath:"children" }]
otherParents: [{ type:Schema.ObjectId, ref:"OtherParent", childPath:"children" }]
});
ChildSchema.plugin(relationship, { relationshipPathName:['parents', 'otherParents'] });
var Child = mongoose.models("Child", ChildSchema)
var parent = new Parent({});
parent.save();
var otherParent = new OtherParent({});
otherParent.save();
var child = new Child({});
child.parents.push(parent);
child.otherParents.push(otherParent);
child.save() //both parent and otherParent children property will now contain the child id
child.remove()