簡潔な答え
これは、MongoDB の設計上の重要な決定事項です 。MongoDB の関係: 埋め込みか参照か?
リレーショナル データベースで行うように、オブジェクトの独立したコピーではなく、オブジェクトへの参照を保存することは、MongoDB で可能であり、多くの場合行われますが、それらを参照する必要があるときに、ますます複雑なクエリが発生するだけです。
長い答え
成分スキーマの定義の一貫性を維持することが目的である場合は、スキーマを定義して、それを 2 回使用できます。成分は独立したコピーとして保存されます。
[{ 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]
});
または、objectId で食材を参照することもできます。
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'}, ]}]
}, ...]
Ingredients への参照を保存する場合のより良い方法は、Ingredients を独自のファースト クラス コレクションとして保存することです。食品を食材ごと、または食材ごとに検索する場合は、依然として多くの個別のクエリが必要になりますが、クエリはより単純になります。
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] を引用すると、「これはリレーショナル データベースが本当に優れているケースの 1 つです」
Id によるサブドキュメントのクエリについては、この SO 投稿を参照してください:
単一のクエリでカテゴリと記事の数を読み取る
ある回答者は、「これは、リレーショナル データベースが真価を発揮するケースの 1 つです」と述べています。