2

I have a match expression in a mongodb aggregation. There are 3 fields that are included in the match but they don't all always contain data. I only want to include the fields in the match if the field isn't empty.

This is what the match looks like if all fields have data but for example, if the array used for studentGradeLevels is empty, then I don't want to include it or I want the query to still return data ignoring the empty parameter.

$match: {
    "school._id": "7011",
    "studentGradeLevels": { $in: ["09", "10", "11", "12"] },
    "contentArea": {
        $in: [
            "English 1"
        ]
    }
}

Is there a way to either dynamically build the match so that I only include the fields I want based on if they are empty or not or do something in the query so that parameters that are empty are ignored.

2 Answers 2

5

You can use $in when the array is not empty and $nin when the array is empty, this way the match field will not be taken into account ($nin : []):

function buildMatch(arr) {
    var matcher = {};
    if (arr.length == 0)
        matcher["$nin"] = arr;
    else
        matcher["$in"] = arr;
    return matcher;
}

var grades = ["09", "10", "11", "12"];
var areas = [ "English 2" ];

var gradeMatch = buildMatch(grades);
var areaMatch = buildMatch(areas);

db.students.aggregate([{
    $match: {
        "school._id": "7011",
        "studentGradeLevels": gradeMatch,
        "contentArea": areaMatch
    }
}])
Sign up to request clarification or add additional context in comments.

1 Comment

It seems like this answers "what if my query parameter is empty." I think the OP wanted this: "If I query for contentArea and schoolGradeLevels and a candidate doc has both fields set, then try to match. But if for example schoolGradeLevels is NOT set in the candidate, then don't even try to match on that field; just try to match on contentArea."
0

A variation: Check fields for existence and if so, change to a special value e.g. _ and add that to the $inlist:

db.foo.aggregate([
{$project: {"studentGradeLevels":{$ifNull: ["$studentGradeLevels","_"]},
            "contentArea":{$ifNull: ["$contentArea","_"]}
}}
,{$match: {
        "studentGradeLevels": { $in: ["_", "09", "10", "11", "12"] },
        "contentArea": { $in: [ "_", "English 1" ]  }
}}
              ]);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.