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 中是可能的,并且经常这样做,当您需要查找它们时,它只会导致越来越复杂的查询。

长答案

如果目标只是保持成分模式的定义一致,您可以定义一个模式并使用它两次。成分将作为独立副本存储,例如

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

通过显式定义成分模式,每个成分对象在声明时都会获得自己的 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 帖子以按 ID 查询子文档: 在单个查询中阅读类别和文章数量

正如一位受访者所说,“这是关系数据库真正大放异彩的案例之一”

于 2013-09-24T19:58:38.363 回答