node.js 使用 Mongoose 进行多对多映射

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11117854/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 15:53:29  来源:igfitidea点击:

Many-to-many mapping with Mongoose

node.jsmongodbmongoose

提问by élodie Petit

I have FlashcardSchemas and PackageSchemas in my design. One flashcard can belong to different packages and a package can contain different flashcards.

我的设计中有 FlashcardSchemas 和 PackageSchemas。一张抽认卡可以属于不同的包,一个包可以包含不同的抽认卡。

Below you can see a stripped down version of my mongoose schema definitions:

您可以在下面看到我的猫鼬模式定义的精简版本:

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

As you can see from the comments above, these two schema definitions belong to separate files and reference each other.

从上面的注释中可以看出,这两个模式定义属于单独的文件并相互引用。

I get an exception stating that PackageSchema is not defined, as expected. How can I map a many-to-many relation with mongoose?

我收到一个异常,说明未按预期定义 PackageSchema。如何映射与猫鼬的多对多关系?

采纳答案by Last Rose Studios

You are doing it the right way, however the problem is that you have to include PackageSchema in the the flashcard-schema.js, and vice-versa. Otherwise these files have no idea what you are referencing

你这样做是正确的,但问题是你必须在 flashcard-schema.js 中包含 PackageSchema,反之亦然。否则这些文件不知道你在引用什么

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

回答by gtsouk

I am new to node, mongoDB, and mongoose, but I think the proper way to do this is:

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

This way, you only store the object reference and not an embedded object.

这样,您只存储对象引用而不是嵌入对象。

回答by Tony O'Hagan

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

您可以使用 Schema.add() 方法来避免前向引用问题。

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

这个(未经测试的)解决方案将架构放在一个 .js 文件中

models/index.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)
};  

回答by Alex

You're thinking of this too much like a relational data store. If that's what you want, use MySQL (or another RDBMS)

您认为这太像关系数据存储了。如果这就是您想要的,请使用 MySQL(或其他 RDBMS)

Failing that, then yes, a third schema could be used, but don't forget it'll still only be the id of each object (no joins, remember) so you'll still have to retrieve each other item in a separate query.

如果失败,那么是的,可以使用第三个模式,但不要忘记它仍然只是每个对象的 id(没有连接,记住)所以你仍然需要在单独的查询中检索每个其他项目.

回答by sudeep_dk

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() 

回答by Lu Tran

This is the problem of cyclic/circular dependency. This is how you make it work in nodejs. For more detail, check out "Cyclic dependencies in CommonJS" at http://exploringjs.com/es6/ch_modules.html#sec_modules-in-javascript

这是循环/循环依赖的问题。这就是你让它在 nodejs 中工作的方式。有关更多详细信息,请查看http://exploringjs.com/es6/ch_modules.html#sec_modules-in-javascript 上的“CommonJS 中的循环依赖项”

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