Reputation: 610
Given the following dummy collection, I want to extract exporting and importing countries for a given resource:
[{
country: "France",
exchange: {
export: [{
resource: "MILK",
origin: ["Toulouse", "Bordeaux"]
}],
import: [{
resource: "BEEF",
origin: ["Lyon", "Marseille"]
}]
}
}, {
country: "Spain",
exchange: {
export: [{
resource: "PORK",
origin: ["Madrid", "Barcelona"]
}],
import: [{
resource: "MILK",
origin: ["Valencia", "Bilbao"]
}]
}
}]
Expected result:
{
resource: "MILK",
exportingCountries: ["France"],
importingCountries: ["Spain"]
}
I've been playing with $group
but I can't find a way to conditionnally $addToSet
countries.
Upvotes: 2
Views: 52
Reputation: 49945
You can use $concatArrays to combine exchange.export
and exchange.import
arrays. This allows you to $group by country
and then you need to get back import
and export
using $filter and $map operators, try:
db.col.aggregate([
{
$project: {
country: 1,
resources: {
$concatArrays: [
{ $map: { input: "$exchange.export", in: { resource: "$$this.resource", exchange: "export" } } },
{ $map: { input: "$exchange.import", in: { resource: "$$this.resource", exchange: "import" } } },
]
}
}
},
{
$unwind: "$resources"
},
{
$group: {
_id: "$resources.resource",
resources: { $addToSet: { country: "$country", exchange: "$resources.exchange" } }
}
},
{
$project: {
_id: 0,
resource: "$_id",
importingCountries: {
$map: {
input: { $filter: { input: "$resources", as: "r", cond: { $eq: [ "$$r.exchange", "import" ] } } },
in: "$$this.country"
}
},
exportingCountries: {
$map: {
input: { $filter: { input: "$resources", as: "r", cond: { $eq: [ "$$r.exchange", "export" ] } } },
in: "$$this.country"
}
}
}
}
])
Output:
{ "resource" : "PORK", "importingCountries" : [ ], "exportingCountries" : [ "Spain" ] }
{ "resource" : "BEEF", "importingCountries" : [ "France" ], "exportingCountries" : [ ] }
{ "resource" : "MILK", "importingCountries" : [ "Spain" ], "exportingCountries" : [ "France" ] }
Upvotes: 1