1

I have two schemas

childrenSchema = new Schema({
  name: String
});

parentSchema = new Schema({
  type: String,
  children: [childrenSchema]
});

Now I want a method in childrenSchema from which I retrieve the type of the parent. I guess it is something like

childrenSchema.methods.generateName = () => {
  // get parent type
};

Do there exist a function like this.parent().type, i.e.

childrenSchema.methods.generateName = () => {
  // get parent type
  return this.parent().type;
};
Jamgreen
  • 10,329
  • 29
  • 113
  • 224
  • `this.ownerDocument()` returns parent document – Ebrahim Pasbani Sep 04 '16 at 08:22
  • Thanks, but it says `this.ownerDocument is not a function`. I have never made a model for my `childrenSchema`. Would it mean that I am not able to make a method for it? It also doesn't find `this.name` even though `childrenSchema` has a field `name`. – Jamgreen Sep 04 '16 at 08:24
  • It should be placed right after defining `childrenSchema` before using it in parent schema – Ebrahim Pasbani Sep 04 '16 at 08:36
  • I do. But it still doesn't recognize `this.fieldName` nor `this.functionName()` – Jamgreen Sep 04 '16 at 08:47

1 Answers1

0

You can do like this :

 childrenSchema = new Schema({
      name: String
    });

    childrenSchema.methods.generateName = () => {
      // get parent type
      return this.ownerDocument().type;
    };

    parentSchema = new Schema({
      type: String,
      children: [childrenSchema]
    });

    var childModel = mongoose.model('Children', childrenSchema);
    var parentModel = mongoose.model('Parent', parentSchema);

    var parent = new parentModel({type: 'Scifi'});
    parent.children.push(new childModel({name: 'Star wars'}));

    parent.save(function(err, doc){
      console.log(doc.children[0].generateName()); // Scifi
    });
Ebrahim Pasbani
  • 9,168
  • 2
  • 23
  • 30
  • Thanks! So it is advised to create a model for each schema (i.e. all sub-schemas) even though I only need the parent model? – Jamgreen Sep 04 '16 at 08:52
  • Great. Thanks. I probably misunderstood something. I thought I could just use the parent model as my only model and push simple javascript objects to its array of sub-documents. But the 'sub-documents' in the array were probably not considered MongoDB documents if I am not creating them with `const subdoc = new SubDocument({})` (opposed to `const subdoc = {}` as I did) – Jamgreen Sep 04 '16 at 08:57
  • @Jamgreen It's up to you follow which pattern. You can define children as `array` and deal with like a normal property in parent. So now this is not subdocument and just be a property. But if you want to define method for subdocument or has a structure so you need to define them as separate shcema-model – Ebrahim Pasbani Sep 04 '16 at 09:01
  • Are there any differences whether I use your approach (with `parent.save()`) instead of `parentModel.findByIdAndUpdate(parentId, { $push: { children: new childModel({ ... }) } }, (err, model) => { ... });`? It seems it is not saved correctly with my approach. Do I have to save the child instance before like `parentModel.findByIdAndUpdate(parentId, { $push: { children: new childModel({ ... }).save() } }, (err, model) => { ... });` – Jamgreen Sep 04 '16 at 09:58
  • @Jamgreen No there is no difference. For ensuring , is your parent doc existed before in db? And for saving child before parent, no need to do that. Because you are embedding child in parent, not referencing it – Ebrahim Pasbani Sep 04 '16 at 10:08
  • Okay. But that also means that I cannot update a children instance with `childModel.findByIdAndUpdate(childId, { ... }, (err, child) => { ... })` even if I know the specific id of the child because the child is only embedded in `parentModel` and thus not exists on its own? – Jamgreen Sep 04 '16 at 10:35
  • @Jamgreen Yes. Child doc does not exist on its own. Because it is embedded. – Ebrahim Pasbani Sep 04 '16 at 10:44