2
\$\begingroup\$

I built an app where a user has a recipe box with recipes in it - for the db, there is a user and recipe model, user has "recipeBox" property. The recipebox is an array of objects like so:

User model....

User.recipeBox = {
["id1", "done": false],
["id1", "done": true],
}

The done property is for a checkbox on the front end. the recipe models have TONS of information and images. so rather than store the entire recipes in a users recipe box, I stored the recipe IDs in a users recipe box (in order to associate the user with the recipes) and I populate them by id in conjunction with a separate recipe model. I'm using Angular on the front-end, and when I was trying to use the powers of angular to persist the checkboxes, I found myself with two separate things to loop through, The User's RecipeBox, checking for ids and the "Done" property, and the recipes in the recipe box, which I had already generated with "populate" in mongoose, from the ids in the recipe box. There was no way to associate the recipe models with the "done" property, the way I had constructed it, so my solution to this on the client was to call a function that put the "done" property on each Recipe (from the User.recipebox). I'm pretty sure the answer is yes, but what is a more efficient way I could have done this with mongodb/mongoose/or any DB language?

I'm transferring the "done" property from the User.recipeBox over to Recipe manually here, to make it easy to use the "item in items" angular syntax:

 function addDonesToNGModel() {

      if ($scope.userRecipes) {

        var box = $scope.currentUser.recipeBox;
        var recipes = $scope.userRecipes;

        console.log(box, recipes);
        for (i = 0; i < box.length; i++) {
          for (var j = 0; j < recipes.length; j++) {

            if (box[i]._id == recipes[j]._id) {
              recipes[j].done = box[i].done;
            }
          }
        }
      }

    }

Models:

'use strict';

var mongoose = require('mongoose');
var recipeSchema = new mongoose.Schema({
  recipeUrl: String,
  image: String,
  numServings: Number,
  Ingredients: [String],
  NutritionalInformation: [{
    attribute: String,
    description: String,
    unit: {
      name: String,
      plural: String
    },
    value: Number
  }],
  // _id: Number,
  name: String,
  createdAt: { type: Date, default: Date.now },
  totalTime: String
});

var Recipe = module.exports = mongoose.model('Recipe', recipeSchema);

'use strict';

var crypto = require('crypto');
var bcrypt = require('bcryptjs');
var mongoose = require('mongoose');
var recipeSchema = require('./recipe.js').schema;
//need the objectID, see: https://gist.github.com/fwielstra/1025038
var Schema = mongoose.Schema;
var ObjectId = Schema.ObjectId;

var userSchema = new Schema({
  email: {
    type: String,
    unique: true
  },
  password: String,
  resetPasswordToken: String,
  resetPasswordExpires: Date,
  image: String,
  picture: ObjectId,
  name: String,
  facebook: {
    id: String,
    token: String,
    pictures: String
  },

  // can refactor this with $populate
   recipeBox: [{
    id: ObjectId,
    done: Boolean
  }]
});
\$\endgroup\$
  • \$\begingroup\$ I am not sure if I got your question fine but if you are asking whether to loop in client's browser or your server, I'd say go with client's resources, not yours. \$\endgroup\$ – mentat Nov 1 '15 at 6:32
  • \$\begingroup\$ I'm asking if a nested for loop on the client is more efficient, or is structuring my models differently the right way to go. point noted! \$\endgroup\$ – devdropper87 Nov 1 '15 at 6:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.