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

1 に答える 1

3

簡潔な答え

これは、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 つです」と述べています。

于 2013-09-24T19:58:38.363 に答える