Coming from a PHP/ MySQL background, I'm struggling with best practices in terms of structuring and saving my data.
I'm trying to create a small application where I can add recipes with multiple ingredients. I have a bunch of pre-populated ingredients as seed data, the schema for which looks like:
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);
A recipe currently looks like this:
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);
Finally, I have a RecipeIngredientSchema. Now, this is where my MySQL background might be creeping in; the reason I've done it this way is because I want the one to many relationship between Recipes and Ingredients, but I also want to be able to specify a unit:
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);
My question comes in two parts:
I'm currently thinking the following:
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);
});
}
});
};
}
}
});
}
I feel this is convoluted and generally wrong, so would appreciate some guidance!
Mongoose | save() Function The save() function is used to save the document to the database. Using this function, new documents can be added to the database.
To update more than one array item matching the criteria in this way, then you need to issue the update several times until the document is no longer modified. So the index position is 0 for the first element, 1 for the second element and so on.
The beauty of NoSQL databases (or document stores in general) is that you don't have to split your data into multiple tables/collections. You can store all the related data into a single entity so that your read operations happen in one shot.
There is no "right" approach to do this, but if you are going to use NoSQL I would consider saving the entire recipe (recipe and ingredients and directions) as a single document rather than splitting the data into 3 or 4 tables a-la relational model.
For example, I would save a single recipe as follows:
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'}
]
}
Now, this is not pixie dust. There will be times where having the data split into multiple tables/collections and having a relational query language (like SQL) will be beneficial to query data. For example, if you wanted to query all recipes that use 'tomatoes' having a relational database with a join table for the recipe/ingredients relations would make this much simpler than the NoSQL approach.
That's a decision that you'll need to make at one point: Are you better of with a NoSQL or with a RBMS for your application?
If you want to save nested objects in DB you have two options: as embedded schema or with ref. If you save them with ref them the nested schema is saved in a separate collection.
Start taking a look at this example mongo-many-to-many and this one section: saving-refs
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With