web-dev-qa-db-fra.com

Mappage plusieurs à plusieurs avec Mongoose

J'ai FlashcardSchemas et PackageSchemas dans ma conception. Une carte mémoire peut appartenir à différents packages et un package peut contenir différentes cartes mémoire.

Ci-dessous, vous pouvez voir une version simplifiée de mes définitions de schéma mangouste:

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

Comme vous pouvez le constater à partir des commentaires ci-dessus, ces deux définitions de schéma appartiennent à des fichiers distincts et se font référence.

Je reçois une exception indiquant que PackageSchema n'est pas défini, comme prévu. Comment puis-je cartographier une relation plusieurs-à-plusieurs avec la mangouste?

39
Élodie Petit

Vous le faites de la bonne façon, mais le problème est que vous devez inclure PackageSchema dans le fichier flashcard-schema.js, et inversement. Sinon, ces fichiers n'ont aucune idée de ce que vous référencez

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 ]
});
3
Last Rose Studios

Je suis nouveau dans les domaines node, mongoDB et mangouste, mais je pense que la bonne façon de procéder est la suivante:

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

De cette façon, vous ne stockez que la référence d'objet et non un objet incorporé.

153
gtsouk

Vous pouvez utiliser la méthode Schema.add () pour éviter le problème de référencement direct.

Cette solution (non testée) place le schéma dans un fichier .js 

models/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)
};  
1
Tony O'Hagan
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's id 
child.remove() 
0
sudeep_dk

C'est le problème de la dépendance cyclique/circulaire. Voici comment vous le faites fonctionner dans nodejs. Pour plus de détails, consultez "Dépendances cycliques dans CommonJS" à http://exploringjs.com/es6/ch_modules.html#sec_modules-in-javascript

//------ a.js ------
var b = require('b');
function foo() {
    b.bar();
}
exports.foo = foo;

//------ b.js ------
var a = require('a'); // (i)
function bar() {
    if (Math.random()) {
        a.foo(); // (ii)
    }
}
exports.bar = bar;

0
Lu Tran

Vous pensez trop à cela comme à un magasin de données relationnel. Si c'est ce que vous voulez, utilisez MySQL (ou un autre SGBDR)

Sinon, un troisième schéma pourrait être utilisé, mais n'oubliez pas qu'il ne s'agira toujours que de l'id de chaque objet (pas de jointure, rappelez-vous), vous devrez donc récupérer chaque élément dans une requête distincte .

0
Alex