Home > OS >  Search query String Array Object in mongoose and use elemMatch is not working as expected
Search query String Array Object in mongoose and use elemMatch is not working as expected

Time:10-18

I am facing with an error which I am unable to resolve it. I want to use query search to search if the data of 1 job matches with user data but I am stucked in some cases. First case it is that my query search of the job looks like this I mean the data.

The problem it is that in the searchFilterSkills.searchSkillsOffer I have an array of objects and I want to match the name of each of them if one of them exist but I am unable to iterate through them because I get an array of Strings with .map() which cannot iterate on it.

After answer from Fabian if all elements matches it returns the elements and it matches but I want if 1 of the elements matches it will return the object. I tried $in but did not work. Is there any query to use instead of $all

These are my data which I try to search.

 "skillsOffer":[
      {
         "name":"Max",
         "rate":0
      },
      {
         "name":"Test",
         "rate":0
      },
      {
         "name":"Javascript",
         "rate":0
      }
   ],
"country":"DEU",
"postalCode":12345

And these are the user Data which he/she has.

"searchFilter" : {
        "remote" : 0,
        "data" : [
            {
                "region" : [
                    "1"
                ],
                "country" : "DEU",
                "searchActive" : false,
                "postalCode" : "123",
                "available" : {
                    "$date" : 1664955924380
                }
            }
        ]
    },
"searchFilterSkills" : {
    "searchSkillsOffer" : [
    {
        "name" : "Javascript",
        "rate" : 100
    },
    {
        "name" : "Test",
        "rate" : 60
    },
    {
        "name" : "Client",
        "rate" : 0
    }
],

}

At skillsOffer I want to search if only the name matches not the rate.

Then if remote is 1 then search the above query and without postalCode with remote or the above one and remote.

async searchUsers(req, res, next) {
        const jobID = req.query.jobID;
        let job = await Job.findById(jobID);
        let postalCode = job.postalCode;
        postalCode = postalCode.toString().slice(0, 1);
        let postalCode2 = job.postalCode;
        postalCode2 = postalCode2.toString().slice(0, 2);
        let postalCode3 =  job.postalCode;
        postalCode3 = postalCode3.toString().slice(0, 3);
        let postalCode4 = job.postalCode;
        postalCode4 = postalCode4.toString().slice(0, 4);
        let postalCode5 =  job.postalCode;
        postalCode5 = postalCode5.toString().slice(0, 0);
        let userIds = job.skillsOffer.map(user => user.name).join(",");
        let users = await User.find({
            "searchFilter.data": {
                $elemMatch: {
                    "$or": [
                        {
                            postalCode: postalCode,
                            
                        },
                        {
                            postalCode: postalCode2,
                        },
                        {
                            postalCode: postalCode3,
                        },
                        {
                            postalCode: postalCode4,
                        },
                        {
                            postalCode: postalCode,
                        },
                        {
                            postalCode: postalCode5,
                        },
        
                    ]
                }
        },
        "searchFilter.data": {
            $elemMatch: {
                country: job.country
            }
        },
    
                    'searchFilterSkills.searchSkillsOffer': {
                    $elemMatch: {
                        name: {
                            $regex: new RegExp(`^${job.skillsOffer.map(jt => jt.name)}`, 'i'), but it does not return a thing here
                        },
                    },

        },
        }); 
        if (job.remote.toString() === "1") {
            users = await User.find({
                "searchFilter.data": {
                    $elemMatch: {
                        "$or": [
                            {
                                postalCode: postalCode,
                                
                            },
                            {
                                postalCode: postalCode2,
                            },
                            {
                                postalCode: postalCode3,
                            },
                            {
                                postalCode: postalCode4,
                            },
                            {
                                postalCode: postalCode,
                            },
                            {
                                postalCode: postalCode5,
                            },
            
                        ]
                    }
            },
            "searchFilter.data": {
                $elemMatch: {
                    country: job.country
                }
            },
    
                "searchFilter.remote": job.remote,
            });
        }

    

        if (!users) {

            res.status(204).json({ error: "No Data" });
            return;
        }
        return res.status(200).send({
            user: users.map(t => 
                t._id
            )
        });
    

    },

CodePudding user response:

I assume you want to match each name from skillsOffer array. This way you have to define an $elemMatch object for each name (basically mapping each name).

You can use the following (partial) query in your code in order to check whether all names are contained in your searchFilterSkills.searchSkillsOffer array.

{
  'searchFilterSkills.searchSkillsOffer': {
    $all: job.skillsOffer
      .map((user) => user.name)
      .map((name) => ({
        $elemMatch: {
          name: {
            $regex: new RegExp(`^${name}$`, 'i'),
          },
        },
      })),
  },
}

If you would like to match any name, you should or the following code:

{
  $or: job.skillsOffer
    .map((user) => user.name)
    .map((name) => ({
      'searchFilterSkills.searchSkillsOffer': {
        $elemMatch: {
          name: {
            $regex: new RegExp(`^${name}$`, 'i'),
          },
        },
      },
    })),
}
  • Related