Home > Software engineering >  filter by reference in mongoose node.jhs
filter by reference in mongoose node.jhs

Time:11-02

I am having the following scenario and I need to understand better how population works: I have 3 schema as below. I need to filter child schema based on grandparent property name. I created a populate on pre find but looks like the populate does not help to filter based on property but only on object ID. The controller code is like below:

filter= {childname: req.params.childname, 'child.parent.grandparent.grandparentname': req.params.grandparent};
const result =  await Child.find(filter)


const childSchema = new mongoose.Schema(
    {
        childname: {
            type: String,
         
    
          },
       
          
          parent:{
            type:mongoose.Schema.ObjectId,
            ref: 'Parent',
            required: [true, "Parent missing"],
           // select: false
    
           }
           
        
    },
    { timestamps: true },
    {
      toJSON: { virtuals: true },
      toObject: { virtuals: true }
    }
);
childSchema.pre(/^find/, function(next) {
  
    this.populate
         (
            {path: 'parent',select: '-__v',
           populate: [
                { path: 'grandparent', select: 'grandparentname' }
                
              ]
    
      
 });
    
  next();
       });
    
  
 const Child = mongoose.model( 'Child', childSchema);
  
 module.exports = Child;


const parentSchema = new mongoose.Schema(
    {
      
          parentname: {
            type: String,
    
          },
          grandparent:{
            type:mongoose.Schema.ObjectId,
            ref: 'grandparent',
            required: [true, "Grand parent missing"],
           // select: false
    
           },
           
        
    },
    { timestamps: true },
    {
      toJSON: { virtuals: true },
      toObject: { virtuals: true }
    }

 );

   const Parent = mongoose.model( 'Parent', parentSchema);
  
  module.exports = Parent;
  
  
  const grandparentSchema = new mongoose.Schema(
    {
      
          grandparentname: {
            type: String,
    
          }
      
         
           
        
    },
    { timestamps: true },
    {
      toJSON: { virtuals: true },
      toObject: { virtuals: true }
    }

 );
    
  
    const Grandparent = mongoose.model( 'Grandparent', grandparentSchema);
  
  module.exports = Grandparent;

CodePudding user response:

I have the answer!

Firstly - remove your Childschema.pre('^/find...

and use next code:

  const result = await Child.aggregate([{
    $match: {
      childname: YOUR_CHILDNAME_VARIABLE,
    }
  }, {
    $lookup: {
      from: 'parents',
      localField: 'parent',
      foreignField: '_id',
      as: 'parent',
      pipeline: [
        {
          "$lookup": {
            "from": "grandparents",
            localField: "grandparent",
            foreignField: "_id",
            "as": "grandparent"
          },
        }, {
          $unwind: '$grandparent'
        },
      ]
    }
  }, {
    $unwind: '$parent'
  }, {
    "$match": {"parent.grandparent.grandparentname": YOUR_GRANDPARENTNAME_VAIRABLE}
  }]);

I tried to do it using populate but haven't had a result :( so, I'v found the solution with aggregate, it works!

  • Related