I have two collections one is company
and other is reports
so below is my company collection.
company collection
[
{
company_id:1,
hubId:4
dimensions:{ region:'North america',country:'USA'},
name:'Amsol Inc.'
},
{
company_id:1,
hubId:4
dimensions:{ region:'North america',country:'Canada'},
name:'Amsol Inc.'
},
{
company_id:2,
hubId:7
dimensions:{ region:'North america',country:'USA',revenue:34555},
name:'Microsoft Inc.'
}
]
reports collection
[
{
report_id:1,
name:'example report',
hubId:4
dimensions:{ region:'North america',country:'USA'},
name:'Amsol Inc.'
},
{
report_id:2,
name:'example report',
hubId:4
dimensions:{ region:'North america',country:'Canada'},
name:'Amsol Inc.'
},
{
report_id:3,
name:'example report',
hubId:5
dimensions:{ region:'North america',country:'USA',revenue:20000},
name:'Microsoft Inc.'
}
{
report_id:4,
name:'example report',
hubId:4
dimensions:{region:'North america',country:'Greenland'},
name:'Amsol Inc.'
},
]
OUTPUT
[
{
report_id:1,
name:'example report',
hubId:4
dimensions:{ region:'North america',country:'USA'},
name:'Amsol Inc.'
},
{
report_id:2,
name:'example report',
hubId:4,
dimensions:{region:'North america',country:'Canada'},
name:'Amsol Inc.'
}
]
I want to fetch all the report that has same HubId
and dimensions
as of companies.
For Ex: hubId = 4
has 2 companies in company
collection but they have different dimensions So here I want to search for all the reports having hubId = 4
and dimensions like matches with any of these companies.
If you noticed
The collections have thousands of records like this.
I have been looking for some aggragation pipeline but fail to understand how can I apply the logic here to get the result here.
Someone help me out to get desired result.Any help appreciated.
CodePudding user response:
If I understand you correctly, a $lookup
with pipeline can do the job:
The let
defines the arguments from the reports
collection, and they are used with $$
inside the $lookup
pipeline. The $
arguments are for the context of the $lookup
pipeline, meaning the company
collection.
The $setEquals
is used to test equality of arrays where the order of items is not important. Here it is used with $objectToArray
to test equality of objects (which are being changed to arrays and then compared).
db.reports.aggregate([
{$lookup: {
from: "company",
let: {hubId: "$hubId", dimensions: "$dimensions"},
as: "companies",
pipeline: [
{$match: {
$expr: {
$and: [
{$eq: ["$hubId", "$$hubId"]},
{$setEquals: [
{$objectToArray: "$dimensions"},
{$objectToArray: "$$dimensions"}
]}
]
}
}},
{$project: {_id: 1}}
]
}},
{$match: {"companies.0": {$exists: true}}},
{$unset: "companies"}
])
See how it works on the playground example