2013-09-24 96 views
1

是否可以在同一模式內引用字段?看我下面的例子。或者我正在討論這種錯誤的方式?同一模式內的參考字段

var UserSchema = new mongoose.Schema ({ 
    username: String, 
    password: String, 
    email: String, 
    foods: [{ 
     name: String, 
     category: String, 
     ingredients: // how to reference values in the ingredients array? 
    }], 
    ingredients: [{ 
     name: String, 
     category: String 
    }] 
}); 

回答

3

簡短的回答

這是一個核心的MongoDB的設計決定:MongoDB relationships: embed or reference?

存儲對象的引用,而不是他們的獨立副本,你會在關係數據庫中做的是可能在MongoDB中,經常這樣做,當你需要查看它時,它會導致越來越複雜的查詢。

龍答案

如果目標只是保持成分模式的定義一致,你可以定義一個模式,並使用它兩次。成分將作爲獨立的副本存儲,例如,

[{ username: 'bob', 
    ingredients: [ { name: 'Carrot', category: 'Vegetable' } , ...], 
    foods: [ { name: 'Salad', category: 'Lunch', ingredients: [ { name: 'Carrot', category: 'Vegetable'}, ...]}] 
}, ...] 


var IngredientSchema = new mongoose.Schema({ 
    name: String, 
    category: String, 
}); 


var UserSchema = new mongoose.Schema ({ 
    username: String, 
    password: String, 
    email: String, 
    foods: [{ 
     name: String, 
     category: String, 
     ingredients: [IngredientSchema] // brackets indicates it's an array, 
    }], 
    ingredients: [IngredientSchema] 
}); 

或者,你可以參考對象ID配料:

var UserSchema = new mongoose.Schema ({ 
    username: String, 
    password: String, 
    email: String, 
    foods: [{ 
     name: String, 
     category: String, 
     ingredients: [mongoose.Schema.Types.ObjectId] // IDs reference individual ingredients, 
    }], 
    ingredients: [IngredientSchema] 
}); 

通過明確界定IngredientSchema,每種成分的對象都有自己的ObjectId當它被宣佈。存儲配料的ID(而不是配料對象的副本)的好處是更簡潔和一致的存儲。缺點是會有更多更復雜的查詢。

[{ username: 'bob', 
    ingredients: [ { _id: ObjectId('a298d9ef898afc98ddf'), name: 'Carrot', category: 'Vegetable' } , ...], 
    foods: [ { name: 'Salad', category: 'Lunch', ingredients: [ {$oid: 'a298d9ef898afc98ddf'}, ]}] 
}, ...] 

,如果你想存儲成分引用一個更好的辦法,可能是配料店作爲自己的頭等集合。如果你想按成分查找食物或食物中的成分,你仍然會有許多單獨的查詢,但查詢會更簡單。

var UserSchema = new mongoose.Schema ({ 
    username: String, 
    password: String, 
    email: String, 
    foods: [{ 
     name: String, 
     category: String, 
     ingredients: [mongoose.Schema.Types.ObjectId] // IDs reference individual ingredients, 
    }], 
    ingredients: [mongoose.Schema.Types.ObjectId] 
}); 

如果目標是基於它們的成分和搜索食品商店標準化引用,引用另一[SO帖] [1],「這是那些情況下,關係型數據庫大放異彩一個」

看到這個SO張貼憑身份證查詢子文檔: Reading categories and number of articles in a single query

一位受訪者指出,「這是那些情況下,關係型數據庫大放異彩一個」

+0

這是否意味着我必須創建兩個模式,如果我想使用引用而不是嵌入?我最初的想法是保持用戶模式下的成分字段,因爲每個用戶都可以定義他們自己的一組成分。現在使用新的IngredientSchema,我將在一個模式(集合)下存儲來自所有用戶的成分。這不是我所需要的。沒有其他方法嗎? – finspin

+0

此外,試圖理解你爲什麼建議參考foods.ingredients領域和配料領域的IngredientSchema。你能解釋一下給我嗎? – finspin

+0

在我給出的例子中,只有一種配料模式,但配料對象在每種食物中獨立存儲,因爲副本不是參考。但我看到你想通過ID來引用成分而不是重複。將編輯上面的答案... – prototype