skip to Main Content

I want to find all task by first_name of claimant.

Task Schema:

const TaskSchema = mongoose.Schema({
    case: {
        type: mongoose.Schema.Types.ObjectId,
        ref: "Case"
    },
});

Case Schema:

const CaseSchema = new mongoose.Schema({
    claimant: {
        type: mongoose.Schema.Types.ObjectId,
        ref: "Claimant"
    },
});

Claimant Schema:

const ClaimantSchema = new mongoose.Schema({
    first_name: {
        type: String,
        required: true,
    },
    last_name: {
        type: String,
        required: true,
    }
});

I tried this but it give empty array:

const searchTasks = await Task.find({ "case.claimant.first_name": "demoName" });

How to do this ?

2

Answers


  1. You can’t directly access nested properties, but you can populate the related data. My playground, you can put all in one file:

    index.js

    require('./playground')();
    

    playground.js

    module.exports = async () => { /* models, data, query */ }
    

    models:

    const TaskSchema = mongoose.Schema({
      name: {
        type: String,
        required: true,
      },
      case: {
        type: mongoose.Schema.Types.ObjectId,
        ref: 'Case',
      },
    });
    const Task = mongoose.model('Task', TaskSchema);
    
    const CaseSchema = new mongoose.Schema({
      name: {
        type: String,
        required: true,
      },
      claimant: {
        type: mongoose.Schema.Types.ObjectId,
        ref: 'Claimant',
      },
    });
    const Case = mongoose.model('Case', CaseSchema);
    
    const ClaimantSchema = new mongoose.Schema({
      first_name: {
        type: String,
        required: true,
      },
    });
    const Claimant = mongoose.model('Claimant', ClaimantSchema);
    

    data:

    const demoClaimant = await Claimant.findOneAndUpdate(
      { first_name: 'demoName' },
      { first_name: 'demoName' },
      { upsert: true, new: true },
    );
    
    const demoCase = await Case.findOneAndUpdate(
      { name: 'case a' },
      { claimant: demoClaimant._id },
      { upsert: true, new: true },
    );
    
    const task = await Task.findOneAndUpdate(
      { name: 'task a' },
      { case: demoCase._id },
      { upsert: true, new: true },
    );
    

    query:

    const searchTasks = await Task.find({})
      .populate({
        path: 'case',
        model: 'Case',
        populate: {
          path: 'claimant',
          model: 'Claimant',
          match: { first_name: 'demoName' },
        },
      }).exec();
    

    filter:

    // Filter out tasks with claimants that have matching first_name
    const filteredTasks = searchTasks.filter(
      (t) => t.case.claimant !== null,
    );
    

    output:

    // console.log(searchTasks)
    // console.log(searchTasks[0].case)
    

    console.log(searchTasks)

    [
      {
        _id: new ObjectId("653251f5f65cdb9e970328f0"),
        name: 'task a',
        __v: 0,
        case: {
          _id: new ObjectId("653251f5f65cdb9e970328eb"),
          name: 'case a',
          __v: 0,
          claimant: [Object]
        }
      }
    ]
    

    console.log(searchTasks[0].case)

    {
      _id: new ObjectId("653251f5f65cdb9e970328eb"),
      name: 'case a',
      __v: 0,
      claimant: {
        _id: new ObjectId("653251f5f65cdb9e970328e1"),
        first_name: 'demoName',
        __v: 0
      }
    }
    

    please inform me about your result.

    Login or Signup to reply.
  2. The most straightforward way you can achieve the desired results is to use aggregate. The mongoose populate method does not allow you to filter the parent documents based on a conditional match on one of the child documents:

    In general, there is no way to make populate() filter stories based on properties of the story’s author. For example, the below query won’t return any results, even though author is populated.

    See the docs for a full explanation. Here is the aggregate solution:

    const searchTasks = await Task.aggregate([
      {
        $lookup: {
          from: "cases", //< I assumed cases collection
          localField: "case",
          foreignField: "_id",
          as: "case"
        }
      },
      {
        $lookup: {
          from: "claimants", //< I assumed claimants collection
          localField: "case.claimant",
          foreignField: "_id",
          as: "case.claimant"
        }
      },
      {
        $match: {
          "case.claimant.first_name": "demoName"
        }
      }
    ]);
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search