$match in $lookup result
Below answer is for mongoDB 3.6 or later.
Given that:
- You have a collection
users
with a fieldCompanyID
and a collection ofcompanies
with a fieldCompanyID
you want to lookup
Companies
onUsers
by matchingCompanyID
, where additionally:- each User must match condition:
User.UserName
equalsadministrator
- each
Company
onUser
must match condition:CompanyName
equalsedt5
- each User must match condition:
The following query will work for you:
db.users.aggregate([
{ $match: { UserName: 'administrator' } },
{
$lookup: {
from: 'companies',
as: 'Company',
let: { CompanyID: '$CompanyID' },
pipeline: [
{
$match: {
$expr: {
$and: [
{ $eq: ['$CompanyID', '$$CompanyID'] },
{ $eq: ['$CompanyName', 'edt5'] },
]
}
}
}
]
}
},
])
Explanation: This is the way to perform left join queries with conditions more complex than simple foreign / local field equality match.
Instead of using localField
and foreignField
, you use:
let
option where you can map local fields to variables,pipeline
option where you can specify aggregationArray
.
In pipeline
you can use $match
filter, with $expr
, where you can reuse variables defined earlier in let
.
More info on $lookup
Nice tutorial
With MongoDB 3.4, you can run an aggregation pipeline that uses the $addFields
pipeline and a $filter
operator to only return the Company
array with elements that match the given condition. You can then wrap the $filter
expression with the $arrayElemAt
operator to return a single document which in essence incorporates the $unwind
functionality by flattening the array.
Follow this example to understand the above concept:
db.users.aggregate([
{ "$match": { "UserName": "administrator" } },
{
"$lookup": {
"from": 'companies',
"localField": 'CompanyID',
"foreignField": 'CompanyID',
"as": 'Company'
}
},
{
"$addFields": {
"Company": {
"$arrayElemAt": [
{
"$filter": {
"input": "$Company",
"as": "comp",
"cond": {
"$eq": [ "$$comp.CompanyName", "edt5" ]
}
}
}, 0
]
}
}
}
])