Reputation: 778
I am creating a MERN app that allows users to sign up and save their skills to a database. I am creating an admin panel that allows me to search for users by skill. User's skills will look like this in the database:
skills: [
{skill: 'React', yearsExperience: 3},
{skill: 'HTML', yearsExperience: 5},
{skill: 'JavaScript', yearsExperience: 5},
{skill: 'Git', yearsExperience: 3},
{skill: 'TypeScript', yearsExperience: 1},
{skill: 'C++', yearsExperience: 1}
]
I have an aggregation query set up that allows me to find all users who match a query by atleast 25%. Meaning if I search for someone with React skills, SQL skills, and C++ skills it will pull back anyone matching at least one of those. My question at this point is how can I modify my aggregation query to create a new field on the document that lists what fields did not match on the query? So this field would show Mark as missing React and SQL skills if he only has C++ experience.
Here is my current query that shows matching users and the percentage they match to the query I search for (in this case greater than 3 years SQL experience, and greater than 2 years GIT experience):
await User.aggregate([
{
$addFields: {
matchingSkills: {
$filter: {
input: '$skills',
cond: {
$or: [
{
$and: [
{ $gt: ['$$this.yearsExperience', 3] },
{ $eq: ['$$this.skill', 'SQL'] },
],
},
{
$and: [
{ $gt: [ "$$this.yearsExperience", 2] },
{ $eq: [ "$$this.skill", "Git"] }
]
}
],
},
},
},
},
},
{
$addFields: {
matchingSkills: '$$REMOVE',
percentageMatch: {
$multiply: [
{ $divide: [{ $size: '$matchingSkills' }, skillSearch.length] },
100,
],
},
},
},
{
$match: { percentageMatch: { $gte: 25 } },
},
]);
Upvotes: 0
Views: 540
Reputation: 51
To get a list of missing skills,
requiredSkills
which will be an array of just the searched skills names.let requiredSkillsStage = {
$addFields: {
matchingSkills: {
$filter: {
input: "$skills",
cond: {
$or: [{
$and: [{
$gt: ["$$this.yearsExperience", 3]
},
{
$eq: ["$$this.skill", "SQL"]
}
]
},
{
$and: [{
$gt: ["$$this.yearsExperience", 2]
},
{
$eq: ["$$this.skill", "Git"]
}
]
}
]
}
}
},
requiredSkills: ["SQL", "Git"]
}
}
$map
to get matched skills' names.let matchingSkillsNamesStage = {
$addFields: {
"matchingSkillsNames": {
$map: {
input: "$matchingSkills",
as: "matchingSkill",
in: "$$matchingSkill.skill"
}
}
}
}
requiredSkills
let missingSkillsStage = {
$addFields: {
"missingSkills": {
$filter: {
input: "$requiredSkills",
cond: {
$not: {
$in: [
"$$this",
"$matchingSkillsNames"
]
}
}
}
}
}
}
Try it out to see how the output would look like
Upvotes: 1