Вопрос по node.js, mongodb, mongoose – Отображение «многие ко многим» с помощью Mongoose

39

У меня есть FlashcardSchemas и PackageSchemas в моем дизайне. Одна карта памяти может принадлежать разным пакетам, а пакет может содержать разные карточки.

Ниже вы можете увидеть урезанную версию моих определений схемы мангуста:

// 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 не определена, как ожидалось. Как я могу сопоставить отношение «многие ко многим» с мангустом?

Когда я вытаскиваю пакет из базы данных, я хочу заполнить массив карточек, а когда я вытаскиваю карту из базы данных, я хочу увидеть, каким пакетам принадлежит эта карта. Если нет простого способа сделать это, должен ли я использовать третью функцию схемы для хранения этих отношений? Élodie Petit
Нет простого способа сделать это - почему у вас есть пакеты, являющиеся частью схемы флэш-карт, и карты, являющиеся частью схемы пакетов? какие запросы вы ожидаете выполнить? Alex

Ваш Ответ

5   ответов
1

You could use the Schema.add() method to avoid the forward referencing problem.

This (untested) solution puts the schema in one .js file

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)
};  
153

Я новичок в нодах, 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'} ]
});

Таким образом, вы сохраняете только ссылку на объект, а не внедренный объект.

@ & # xC9; lodie-petit, пожалуйста, сделайте этот ответ принятым.
Просто хочу указать, что это правильный путь для отношений многих со многими. Принятый ответ неверен.
Цитировать из "заполнить" документ:It is debatable that we really want two sets of pointers as they may get out of sync. Instead we could skip populating and directly find() the stories we are interested in.  Это заставляет меня думать, что в одной из схем должен быть только один массив ref. Если в обеих схемах действительно есть массивы ref, вы должны обеспечить сохранение только карт с пакетами ИЛИ пакетов с картами. Я не эксперт по мангусту, хотя.
@TyMayn Должно быть указано имя модели, а не имя схемы. Обычно FlashcardSchema должна генерировать модель с именем Flashcard.mongoosejs.com/docs/models.html
0
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() 
3

однако проблема в том, что вам нужно включить 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 ]
});
Ответить @gtsouk
Будьте осторожны при использовании этого метода. Как вы храните на объекте, а не только его ID, если вы измените «пакет» привязанный к вашей "карточке", он не будет изменен на вашей "карточке".
НЕПРАВИЛЬНЫЙ ОТВЕТ. Ответ ниже правильный. Этот ответ вводит в заблуждение и вдобавок к этому принимается как правильный ответ.
@TonyOHagan нет, Node обрабатывает требуемый цикл, как описано вnodejs.org/api/all.html#all_cycles
Не приведет ли это к бесконечной рекурсии, поскольку каждый require () загружает другой?
0

Это проблема циклической / круговой зависимости. Вот как вы заставляете это работать в nodejs. Для более подробной информации, ознакомьтесь с «Циклическими зависимостями в 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;

Похожие вопросы