mascor
mascor

Reputation: 23

Nodejs/MongoDB : $in needs an array

what I am trying to do , is to join two collections and then return elements whome names exist inside an array

these are the models

CarModel

id,
carAuthorizedDrivers:[String],
garageId:{type: Schema.ObjectId,ref:"garage"}

driversModel

id,
garageId:{type: Schema.ObjectId,ref:"garage"}
drivers:[{name:String,skill:String}]

this is the result of the join

{
"id":"1D99399379773",
"carAuthorizedDrivers":["DriverA","DriverB"],
"garageId":"010003",
"JoinDrivers":[drivers:[{"name":"DriverA","skill":"89"},{"name":"DriverB","skill":"77"},{"name":"DriverC","skill":"45"}]]
}

I want to restrict Joindrivers for the purpose of only showing drivers(name+skills) whome names belong to carAuthorizedDrivers , so I want joinDrivers to contain only the following :

{"name":"DriverA","skill":"89"},{"name":"DriverB","skill":"77"}

what i tried to do is the following :

join () {
    return new Promise(function (resolve, reject) {
      Car.aggregate([
        {
          $lookup: {
            from: 'drivers', // collection name in db
            localField: 'garage_id',
            foreignField: 'garage_id',
            as: 'joinDrivers'
          }
        },
        { $unwind: '$Joindrivers' },
        { $unwind: '$Joindrivers.drivers' },
        { $unwind: '$carAuthorizedDrivers' },
        { $match: { 'Joindrivers.drivers.name': { $in: 'carAuthorizedDrivers' } } }
      ]).exec((err, result) => {
        if (err) {
          reject(err)
        }
        resolve(result)
      })
    })
  }

I get $in needs an array ERROR , but if I put an Array manually like this :

$match: { 'Joindrivers.drivers.name': { $in: ["DriverA","DriverB"] } }  

$in works well and I get the result , how do I solve this issue ?

Upvotes: 0

Views: 3260

Answers (2)

prasad_
prasad_

Reputation: 14287

To compare or match two document fields within an aggregation's $match stage, you have to use an aggregation operator $in (not the query language operator $in). And, to use the aggregation operator in the $match stage, you must use the $expr operator.

So, your match stage should be:

{ $match: { $expr: { $in: [ "$Joindrivers.drivers.name", "$carAuthorizedDrivers" ] } } }



The following code uses the output from the lookup stage to filter based on the provided condition:

db.collection.aggregate( [
{ $unwind: "$JoinDrivers" },
{ $addFields: { 
       "JoinDrivers.drivers": {
            $filter: {
                input: "$JoinDrivers.drivers", as: "driver",
                cond: {
                    $in: [ "$$driver.name", "$carAuthorizedDrivers" ] 
                }
            }
       }
}},
] )

Upvotes: 5

Wernfried Domscheit
Wernfried Domscheit

Reputation: 59456

You mixed the Query operator $in with the Aggregation operator $in

Try this one:

{ $match: { $in: ["$Joindrivers.drivers.name", ["DriverA", "DriverB"] } }  

Upvotes: 0

Related Questions