2012-06-20 108 views
34

我在設計中使用了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

有沒有簡單的方法來做到這一點 - 爲什麼你有軟件包的閃卡模式的一部分,和閃卡的包模式的一部分?你期望運行哪些查詢? – Alex

+0

當我從數據庫中取出一個包時,我想填充卡陣列,當我從數據庫中取出一張卡時,我想查看卡所屬的包。如果沒有一個簡單的方法來做到這一點,我應該使用第三個模式函數來存儲這些關係嗎? –

回答

5

你正在做正確的方式,但問題是,你必須包括PackageSchema的燒錄卡,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 ] 
}); 
+1

這不會導致無限遞歸,因爲每個require()會加載另一個嗎? –

+3

@TonyOHagan否,Node按照http://nodejs.org/api/all.html#all_cycles – FGM

+2

中的說明處理require循環。使用此方法時請小心。當你存儲在對象上而不僅僅是它的ID時,如果你修改了鏈接到「flashcard」的「包」,它將不會在你的「flashcard」中被修改。 – Tim

0

您正在考慮像關係數據存儲一樣太多。如果這就是你想要的,使用MySQL(或其他RDBMS)

如果沒有,那麼是的,可以使用第三個模式,但不要忘記它仍然只是每個對象的id(沒有連接,記住),所以你仍然需要在單獨的查詢中檢索其他項目。

+0

我必須考慮這個像關係型dbms的唯一地方就是這種包卡情況。否則,你是絕對正確的。 –

+0

根據這個答案中的「no joins」評論,請注意,2015年發佈的MongoDB現在有$ lookup aggregator(https://docs.mongodb.com/manual/reference/operator/aggregation/lookup/),它執行左外部加入。 – ryanm

0

您可以使用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) 
}; 
126

我是新來的節點,MongoDB的,和貓鼬,但我認爲正確的做法是:

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

這樣,你只有sto重新引用對象而不是嵌入對象。

+11

http://mongoosejs.com/docs/populate.html –

+0

好找到工作的這個鏈接@Ruairi – gtsouk

+9

只是想指出,這是許多一對多的關係的正確途徑。接受的答案是錯誤的。 – volatilevar

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