在mongoose中保存嵌套对象

Jam*_*mes 14 mongoose mongodb node.js express

来自PHP/MySQL背景,我在构建和保存数据方面遇到了最佳实践.

我正在尝试创建一个小应用程序,我可以添加多种成分的食谱.我有一堆预先填充的成分作为种子数据,其架构如下所示:

var IngredientSchema = new Schema({
    name: {
        type: String,
        trim: true,
        required: true,
        index: {
            unique: true
        }
    },
    created: {
        type: Date,
        default: Date.now
    }
});

var Ingredient = mongoose.model('Ingredient', IngredientSchema);
Run Code Online (Sandbox Code Playgroud)

配方目前看起来像这样:

var RecipeSchema = new Schema({
    name: {
      type: String,
      trim: true
    },
    ingredients: [
      {
        type: Schema.Types.ObjectId,
        ref: 'RecipeIngredient'
      }
    ],
    created: {
      type: Date,
      default: Date.now
    }
});

var Recipe = mongoose.model('Recipe', RecipeSchema);
Run Code Online (Sandbox Code Playgroud)

最后,我有一个RecipeIngredientSchema.现在,这是我的MySQL背景可能正在蔓延的地方; 我这样做的原因是因为我想要食谱和配料之间的一对多关系,但我也希望能够指定一个单位:

var RecipeIngredientSchema = new Schema({
    recipe: {
      type: Schema.Types.ObjectId,
      ref: 'Recipe'
    },
    ingredient: {
      type: Schema.Types.ObjectId,
      ref: 'Ingredient'
    },
    unit: {
      type: Schema.Types.ObjectId,
      ref: 'Unit'
    },
    created: {
      type: Date,
      default: Date.now
    }
});

var RecipeIngredient = mongoose.model('RecipeIngredient', RecipeIngredientSchema);
Run Code Online (Sandbox Code Playgroud)

我的问题分为两部分:

  • 我是否会在数据建模方面以合理的方式解决这个问题,或者我是否会离开?
  • 用多种成分保存食谱的过程实际上是什么样的?

我目前正在考虑以下问题:

exports.create = function(req, res) {

  var recipe = new Recipe(req.body);

  recipe.save(function(err, recipe) {
    if (err) {
      return res.jsonp(err);
    } else {

      // Loop ingredients
      if (req.body.ingredients) {
        for(var prop in req.body.ingredients) {
          var recipeIngredient = new RecipeIngredient({
            recipeId: recipe._id,
            ingredientId: mongoose.Types.ObjectId(req.body.ingredients[prop])
          });

          recipeIngredient.save(function(err, recipeIngredient) {
            if (err) {
              return res.jsonp(err);
            } else {
              recipe.recipeIngredients.push(recipeIngredient._id);
              recipe.save(function(err, recipe) {
                return res.jsonp(recipe);
              });
            }
          });
        };
      }
    }
  });
}
Run Code Online (Sandbox Code Playgroud)

我觉得这很复杂,而且总体上是错误的,所以会很感激一些指导!

Hec*_*rea 9

NoSQL数据库(或一般的文档存储)的优点在于您不必将数据拆分为多个表/集合.您可以将所有相关数据存储到单个实体中,以便一次性执行读取操作.

没有"正确"的方法来做到这一点,但是如果你打算使用NoSQL,我会考虑将整个配方(配方和成分和方向)保存为单个文档,而不是将数据分成3或4个表a-la关系模型.

例如,我会保存一个食谱,如下所示:

recipe = {
    name: 'name of recipe'
    time: '45 minutes'
    ingredients : [
       {qty: 3, unit: 'item', name: 'tomatoes'},
       {qty: 0.5, unit: 'tbs', name: 'salt'},
       {qty: 1, name: 'item', name: 'avocado'} 
    ]
}
Run Code Online (Sandbox Code Playgroud)

现在,这不是小精灵的尘埃.有时将数据拆分成多个表/集合并使用关系查询语言(如SQL)将有利于查询数据.例如,如果您想查询所有使用'tomato'的配方,这些配方使用关系数据库和配方/配料关系的连接表,这将比NoSQL方法简单得多.

这是您需要做出的决定:您是否更适合使用NoSQL或RBMS用于您的应用程序?

  • 我不同意你的观点,即"找到所有使用'西红柿'的食谱".使用你的例子,你只需要`recipes.find({'ingredients.name':'tomatoes'})`.Mongo读取速度非常快,所以这应该比sql中的JOIN快得多. (7认同)