Home > Mobile >  (Mongodb) Getting an error (BadValue) $in needs an array , when using $map aggregate function
(Mongodb) Getting an error (BadValue) $in needs an array , when using $map aggregate function

Time:10-20

I am trying to convert array of strings to array of ObjectId using map function, map will return me array of ObjectIds that I am using in $match to check if _id matches with any of objectids present in array using $in operator.

Database configuration is

 db={
  "students": [
    {
      "_id": ObjectId("5c1a79f7c98da061141475b7"),
      "firstName": "Ibrahim",
      "kelasID": ObjectId("5c429f9906f2a805bc6cd494"),
      "lastName": "Ali",
      "schoolID": ObjectId("5c1a735fc98da061141475a1"),
      "year": 2018,
      "__v": 0,
      "addedOn": ISODate("2018-12-25T04:27:47.909Z"),
      "checkIn": false,
      "checkInStatus": 1,
      "contactNo1": "012225656",
      "father": "Ali",
      "fatherID": "8852245",
      "idType": 0,
      "lastModified": ISODate("2018-12-25T04:27:47.909Z"),
      "mother": "",
      "motherID": ""
    },
    {
      "_id": ObjectId("5c3bfea37774fb0b55000cb5"),
      "idType": 0,
      "checkIn": false,
      "checkInStatus": 1,
      "year": 2019,
      "schoolID": ObjectId("5c1a735fc98da061141475a1"),
      "kelasID": ObjectId("5c1a7534c98da061141475a3"),
      "firstName": "Umar",
      "lastName": "Bin Al-Khattab",
      "contactNo1": "601222",
      "status": 1,
      "addedOn": ISODate("2019-01-14T03:14:43.597Z"),
      "lastModified": ISODate("2019-01-14T03:14:43.597Z"),
      "__v": 0
    },
    {
      "_id": ObjectId("5c1a7c69c98da061141475bb"),
      "idType": 0,
      "checkIn": false,
      "checkInStatus": 1,
      "year": 2018,
      "schoolID": ObjectId("5c1a735fc98da061141475a1"),
      "kelasID": ObjectId("5c1a7540c98da061141475a5"),
      "firstName": "Abdul Rahman",
      "lastName": "Affan",
      "father": "Affan",
      "fatherID": "54321",
      "contactNo1": "602288",
      "status": 1,
      "addedOn": ISODate("2018-12-25T04:30:16.130Z"),
      "lastModified": ISODate("2018-12-25T04:30:16.130Z"),
      "__v": 0
    }
  ]
}

and the query is

db.students.aggregate([
  {
    "$match": {
      "_id": {
        $in: {
          "stud": {
            "$map": {
              "input": [
                "5c1a79f7c98da061141475b7",
                "5c3bfea37774fb0b55000cb5",
                "5c1a7c69c98da061141475bb",
                "5c3bfea37774fb0b55000cb4",
                "5c1a7d32c98da061141475be",
                "5c3bfea37774fb0b55000cb7"
              ],
              "in": {
                "$toObjectId": "$$this"
              }
            }
          }
        }
      }
    }
  }
])

You can also check this out here- https://mongoplayground.net/p/8tQFHxtrttW The above doesn't work but if I change the query like below it works.

db.students.aggregate([
  {
    "$match": {
      "_id": {
        $in: [
          ObjectId("5c1a79f7c98da061141475b7"),
          ObjectId("5c3bfea37774fb0b55000cb5")
        ]
      }
    }
  }
])

Link to above query- https://mongoplayground.net/p/cjq77KIAcPE

Error i'm getting - query failed: (BadValue) $in needs an array Can anybody help with the reason to the error , as according to docs map does return an array , so what am I doing wrong?

CodePudding user response:

Not sure why it doesn't work it might have to do with $in operator and $in aggregation. When you use an array that is defined by a variable you can use $in operator but when you are using aggregation result ( in this case $map ) you have to use $in aggregation. But to use $in aggregation you need to work with $expr for $match.

You can try the below code which works fine

db.students.aggregate([
      {
        $addFields: {
          studentIds: {
            $map: {
              input: [
                "5c1a79f7c98da061141475b7",
                "5c3bfea37774fb0b55000cb5",
                "5c1a7c69c98da061141475bb",
                "5c3bfea37774fb0b55000cb4",
                "5c1a7d32c98da061141475be",
                "5c3bfea37774fb0b55000cb7",
              ],
              in: {
                $toObjectId: "$$this",
              },
            },
          },
        },
      },
    
      {
        $match: {
          $expr: {
            $in: ["$_id", "$studentIds"],
          },
        },
      },
   ]);

or if you want to combine the two of the stages you can do it like this

db.students.aggregate([
{
    $match: {
      $expr: {
        $in: [
          "$_id",
          {
            $map: {
              input: [
                "5c1a79f7c98da061141475b7",
                "5c3bfea37774fb0b55000cb5",
                "5c1a7c69c98da061141475bb",
                "5c3bfea37774fb0b55000cb4",
                "5c1a7d32c98da061141475be",
                "5c3bfea37774fb0b55000cb7",
              ],
              in: {
                $toObjectId: "$$this",
              },
            },
          },
        ],
      },
    },
  },
]);

If anything I missed or it doesn't work do let me know. I hope this solves your problem. Happy coding.

  • Related