I have next mongo code:
db.users.aggregate([ { $match: { $and: [ { UserName: { $eq: 'administrator' } }, { 'Company.CompanyName': { $eq: 'test' } } ] } }, { $lookup: { from: "companies", localField: "CompanyID", foreignField: "CompanyID", as: "Company" } }, ])
The $lookup
part of the code working great. I got next result:
But if I add $match
to the code, it brings nothing.
I found that the problem is in the second match: { 'Company.CompanyName': { $eq: 'test' } }
, but I can not realize what is wrong with it. Any ideas?
UPDATE:
I had also tried $unwind
on the $lookup
result, but no luck:
db.users.aggregate([ { $match: { $and: [ { UserName: { $eq: 'administrator' } }, { 'Company.CompanyName': { $eq: 'edt5' } } ] } }, { unwind: '$Company' }, { $lookup: { from: 'companies', localField: 'CompanyID', foreignField: 'CompanyID', as: 'Company' } }, ])
The MongoDB $match operator filters the documents to pass only those documents that match the specified condition(s) to the next pipeline stage.
The $match stage of the pipeline can be used to filter documents so that only ones meeting certain criteria move on to the next stage. In this article, we'll discuss the $match stage in more detail and provide examples that illustrate how to perform match aggregation in MongoDB.
Equality Match with a Single Join Condition Starting in MongoDB 5.1, the collection specified in the from parameter can be sharded. Specifies the field from the documents input to the $lookup stage. $lookup performs an equality match on the localField to the foreignField from the documents of the from collection.
js. The $lookup operator is an aggregation operator or an aggregation stage, which is used to join a document from one collection to a document of another collection of the same database based on some queries. Both the collections should belong to the same databases.
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 ] } } } ])
Below answer is for mongoDB 3.6 or later.
Given that:
users
with a field CompanyID
and a collection of companies
with a field CompanyID
you want to lookup Companies
on Users
by matching CompanyID
, where additionally:
User.UserName
equals administrator
Company
on User
must match condition: CompanyName
equals edt5
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 aggregation Array
.In pipeline
you can use $match
filter, with $expr
, where you can reuse variables defined earlier in let
.
More info on $lookup
Nice tutorial
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With