使用Mongoose进行多对多映射

8 浏览
0 Comments

使用Mongoose进行多对多映射

我设计中有FlashcardSchemas和PackageSchemas。一个flashcard可以属于不同的packages,而一个package可以包含不同的flashcards。

下面是我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未定义,这是预料之中的。我如何在mongoose中映射一个多对多关系?

0
0 Comments

问题的原因是在flashcard-schema.js文件中需要引入PackageSchema,反之亦然。否则,这些文件不知道你在引用什么。

解决方法是在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 ]
});

这样做不会导致无限递归,因为Node会处理require循环,具体解释可以在nodejs.org/api/all.html#all_cycles上找到。

需要注意的是,当你使用这种方法时要小心。因为你存储的是一个对象而不仅仅是它的ID,所以如果你修改与"flashcard"相关联的"package",它不会在"flashcard"中被修改。

错误答案。下面的答案是正确的。这个答案是误导性的,而且还被接受为正确答案。

还有其他4个答案。哪一个是正确的答案?

回答者:

0
0 Comments

在使用node、mongodb和mongoose的过程中,我发现了一个问题:如何实现多对多的映射关系。经过一番探索,我找到了解决方法。

首先,我们可以使用以下代码定义Package和Flashcard的Schema:

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

通过这种方式,我们只存储对象的引用,而不是嵌入对象本身。

然而,有一些疑问需要解答:在上述代码中,ref:'Flashcard'ref:'Package'是否应该与Schema的名称匹配,还是任意指定?换句话说,它应该是FlashcardSchema吗?答案是应该设置为模型的名称,而不是Schema的名称。通常,FlashcardSchema应该生成一个名为Flashcard的模型。

此外,某些情况下可以使用populate来查找相关文档,但这可能导致两个指针集不同步的问题。因此,我们可以直接使用find()方法来查找我们感兴趣的flashcards或packages。

最后,有人问如何在这种关系中进行搜索,例如,如果要查找所有在packages列表中具有特定id的FlashcardSchema文档。这可以通过以下方式实现:

FlashcardSchema.find({ packages: { $in: [specificId] } }, function(err, flashcards) {
    // 处理查询结果
});

以上代码将查找所有在packages列表中包含特定id的FlashcardSchema文档。

通过使用mongoose的引用和查询方法,我们可以轻松地实现多对多的映射关系。

0
0 Comments

在Mongoose中,一个常见的问题是如何处理多对多的映射关系。这个问题的出现是因为在定义Schema时,无法直接引用另一个还未定义的Schema。

为了解决这个问题,可以使用Mongoose的Schema.add()方法来避免前向引用问题。下面是一个示例的解决方案的代码示例,将Schema定义在一个单独的.js文件中。

models/index.js:

var Schema = mongoose.Schema,
    ObjectId = Schema.ObjectId;
// 避免前向引用问题
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 ]
});
// 导出两种类型
module.exports = {
    Package:   mongoose.model('Package', PackageSchema),
    Flashcard: mongoose.model('Flashcard', FlashcardSchema)
};

通过使用Schema.add()方法,我们可以在定义PackageSchema和FlashcardSchema时,分别引用彼此。这样就解决了前向引用问题,实现了多对多的映射关系。

以上是解决Mongoose中多对多映射关系的问题的方法。通过使用Schema.add()方法,我们可以避免前向引用问题,并成功定义多对多的映射关系。

0