58

I'm beginning with Mongoose and I want to know how to do this type of configuration:

enter image description here

A recipe has different ingredients.

I have my two models:

Ingredient and Recipe:

var mongoose = require('mongoose');
var Schema = mongoose.Schema;

var IngredientSchema = new Schema({
    name: String
});

module.exports = mongoose.model('Ingredient', IngredientSchema);
var mongoose = require('mongoose');
var Schema = mongoose.Schema;

var RecipeSchema = new Schema({
    name: String
});

module.exports = mongoose.model('Recipe', RecipeSchema);
ggorlen
  • 44,755
  • 7
  • 76
  • 106
devtest654987
  • 583
  • 1
  • 4
  • 4

1 Answers1

107

Check Updated code below, in particular this part: {type: Schema.Types.ObjectId, ref: 'Ingredient'}

var mongoose = require('mongoose');
var Schema = mongoose.Schema;

var IngredientSchema = new Schema({
    name: String
});

module.exports = mongoose.model('Ingredient', IngredientSchema);
var mongoose = require('mongoose');
var Schema = mongoose.Schema;

var RecipeSchema = new Schema({
    name: String,
    ingredients:[
      {type: Schema.Types.ObjectId, ref: 'Ingredient'}
    ]
});

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

To Save:

var r = new Recipe();

r.name = 'Blah';
r.ingredients.push('mongo id of ingredient');

r.save();
ggorlen
  • 44,755
  • 7
  • 76
  • 106
Tim
  • 2,695
  • 3
  • 33
  • 39
  • How am I saving ? for this moment, I am saving like this : .post(function(req, res) { var recipe = new Recipe(); recipe.name = req.body.name; recipe.save(function(err) { if (err) res.send(err); res.json({ message: 'recipe created' }); }); }) – devtest654987 Sep 24 '14 at 04:53
  • You would need to save ingredients separately and then push id into array. – Tim Sep 24 '14 at 05:00
  • 1
    I tried this: `var ChildSchema = new Schema({ name: String }); mongoose.model('Child', ChildSchema); var ParentSchema = new Schema({ name: String, children: [{ childId: { type: ObjectId, ref: 'Child', required: true } }] }); mongoose.model('Parent', ParentSchema);`. When I push the child into the parent document, like this: `parent.locations.push({ childId: child.id });parent.save();`, the document looks like this: `{ "name" : "Bob", "children" : [ { "childId" : ObjectId("57769de13eaeda6020b522f2"), "_id" : ObjectId("5776a23a511539a421824c27") } ] }`. Why is there both a `childId` and an `id`? – Web User Jul 01 '16 at 17:24
  • 1
    @Web User You can either replace childId with _id or in your schema: .... children: [_id:false, { childId: { type: ObjectId, ref: 'Child', required: true } }] I hope this helps – Tim Jul 02 '16 at 04:20
  • @Tim Because `child` has its own collection, I couldn't disable `_id` in `ChildSchema`. I created a new schema just to specify `{ _id: false }`, not knowing use of `_id` can be disabled right there while specifying the structure for `children`. Can you *please* help me with this other [question](http://stackoverflow.com/questions/38155298/how-to-update-mongodb-documents-with-arrays-of-sub-documents) I posted? Long story short, I am dealing with a schema that contains an array of sub-document which in turn contain an array of sub-documents. I need to add/update/delete at both levels. Thanks! – Web User Jul 02 '16 at 04:30
  • How it's possible to find the ingredient name object inside recipe object with find query ? Could you showing an example with a find query please ? – John Sep 09 '16 at 07:49
  • 1
    @John there are multiple way of doing that, John just post another question post a link here and I will try to answer it since this comments thread getting bigger. Thanks – Tim Sep 11 '16 at 23:06
  • I did a post here http://stackoverflow.com/questions/39575393/mongoose-multiple-synchronous-find-to-reuse-object-id – John Sep 19 '16 at 15:10
  • I guess the two schemas are in the same files, right? – jsh6303 Oct 28 '17 at 19:55
  • 1
    @jsh6303 Can be in the same file can be in different files does not really matter. As long as it defined and included – Tim Oct 29 '17 at 21:20
  • and if you do r.ingredients.push() many times with the same foreign key, is this possible? – Olivier Pons Mar 27 '18 at 23:04
  • @OlivierPons Yes it should not be a problem – Tim Mar 28 '18 at 02:47
  • @Tim Sorry I didn't express myself: if I want to be able to have only once the same ingredient, and I want `r.ingredients.push()` twice with the same ingredient to be a problem (actually), how would you deal with this? – Olivier Pons Mar 31 '18 at 07:47
  • @OlivierPons you can have validation inside mongoose model.pre('save'), but that would not be atomic, another approach is to create unique index on subdocument see this article http://joegornick.com/2012/10/25/mongodb-unique-indexes-on-single-embedded-documents/ I hope this helps – Tim Apr 03 '18 at 01:25
  • 1
    does this method do validation of that foreign key i.e the _id in the schema with a "ref" property, should actually point to the referenced Model and ensure that the referenced Model contains exactly the same – hane Smitter Sep 18 '21 at 13:30
  • 1
    No it does not validate, but you can validate on pre and post hooks – Tim Oct 05 '21 at 03:06