Reputation: 79
Good day all,
i need some help in getting an aggregation pipeline to work, been trying to get it working for some time but getting only half way. this is my setup
Users document is as follow:
{
"_id": { "$oid": "5fea4f976ca46d93c010d33d" },
.....................
"firstname": "firstname1",
"lastname": "lastname1",
"key1": "value1",
"key2": "value2",
"key3": "value3",
"key4": "value4",
..................
"certifications": {
certs: [
{
"_id": "5fea44b96ca46d93c010d330",
"itemID": 1,
"date_certified": "2011-05-30 05:09:48"
},
{
"_id": "5fea44b96ca46d93c010d334",
"itemID": 3,
"date_certified": "2007-01-30 06:01:51"
},
{
"_id": "5fea44b96ca46d93c010d337",
"itemID": 5,
"date_certified": "2007-09-21 16:52:52"
}
]
},
.......................
...................
.....................
},
{
"_id": { "$oid": "5fea4f976ca46d93c010545453" },
.....................
.....................
"firstname": "firstname2",
"lastname": "lastname2",
"key1": "value1",
"key2": "value2",
"key3": "value3",
"key4": "value4",
..................
"certifications": {
certs: [
{
"_id": "5fea44b96ca46d93c010d330",
"itemID": 2,
"date_certified": "2011-05-30 05:09:48"
},
{
"_id": "5fea44b96ca46d93c010d334",
"itemID": 4,
"date_certified": "2007-01-30 06:01:51"
}
]
},
.......................
...................
.....................
}
Certifications document is a follow
[{
"_id": {
"$oid": "5fea44b96ca46d93c010d32e"
},
"itemID": 1,
"acronym": "acro1",
"country": "my Great Country",
"name": {
"key1": "My Key 1 description",
"key2": "My Key 2 description",
"key3": "My Key 3 description",
"key4": "My Key 4 description"
},
"website": "www.myGreatWebsite.com"
},
{
"_id": {
"$oid": "5fea44b96ca46d93c010d32f"
},
"itemID": 2,
"acronym": "acro2",
"country": "my Great Country",
"name": {
"key1": "My Key 1 description",
"key2": "My Key 2 description",
"key3": "My Key 3 description",
"key4": "My Key 4 description"
},
"website": "www.myGreatWebsite.com"
},
{
"_id": {
"$oid": "5fea44b96ca46d93c010d330"
},
"itemID": 3,
"country": "my Great Country",
"name": {
"key1": "My Key 1 description",
"key2": "My Key 2 description",
"key3": "My Key 3 description",
"key4": "My Key 4 description"
},
"website": "www.myGreatWebsite.com"
},
{
"_id": {
"$oid": "5fea44b96ca46d93c010d331"
},
"itemID": 4,
"country": "my Great Country",
"name": {
"key1": "My Key 1 description",
"key2": "My Key 2 description",
"key3": "My Key 3 description",
"key4": "My Key 4 description"
},
"website": "www.myGreatWebsite.com"
},
{
"_id": {
"$oid": "5fea44b96ca46d93c010d332"
},
"itemID": 5,
"country": "my Great Country",
"name": {
"key1": "My Key 1 description",
"key2": "My Key 2 description",
"key3": "My Key 3 description",
"key4": "My Key 4 description"
},
"website": "www.myGreatWebsite.com"
}]
now my aggregation
db.users.aggregate([
{
'$lookup': {
'from': 'certifications',
'let': {
'certs': '$certifications.certs'
},
'pipeline': [
{
'$match': {
'$expr': {
'$in': [
'$itemID', '$$certs.itemID'
]
}
}
}, {
'$project': {
'_id': 0,
'itemID': '$itemID',
'description': '$name.key1',
'acronyme': '$acronym',
'country': '$country',
'count': {
'$size': '$$certs'
},
'date_cert': '$$certs.date_certified'
}
}
],
'as': 'certifications'
}
}
])
and the result is
{
.........
...........
"firstname": "firstname1",
"lastname": "lastname1",
"key1": "value1",
"key2": "value2",
"key3": "value3",
"key4": "value4",
..................
certification: {
certs: [
{
itemID: 1,
country: 'my Great Country',
description: 'My Key 1 description',
count: 1,
date_cert: [
0:"2005-01-06 10:48:16"
]
},
]
}
........
.........
},
{
.........
...........
"firstname": "firstname2",
"lastname": "lastname2",
"key1": "value1",
"key2": "value2",
"key3": "value3",
"key4": "value4",
..................
certification: {
certs: [
{
itemID: 2,
country: 'my Great Country',
description: 'My Key 2 description',
count: 2,
date_cert: [
"2005-01-06 10:48:16"
"2014-06-21 22:44:56"
]
},
{
itemID: 4,
country: 'my Great Country',
description: 'My Key 4 description',
count: 2,
date_cert: [
"2005-01-06 10:48:16"
"2014-06-21 22:44:56"
]
}
]
}
........
.........
}
but the expected result is
{
.........
...........
"firstname": "firstname1",
"lastname": "lastname1",
"key1": "value1",
"key2": "value2",
"key3": "value3",
"key4": "value4",
..................
certification: {
certs: [
{
itemID: 1,
country: 'my Great Country',
description: 'My Key 1 description',
date_cert: "2005-01-06 10:48:16"
},
],
count: 1,
}
........
.........
},
{
.........
...........
"firstname": "firstname2",
"lastname": "lastname2",
"key1": "value1",
"key2": "value2",
"key3": "value3",
"key4": "value4",
..................
certification: {
certs: [
{
itemID: 2,
country: 'my Great Country',
description: 'My Key 2 description',
date_cert: "2005-01-06 10:48:16"
},
{
itemID: 4,
country: 'my Great Country'
description: 'My Key 4 description',
date_cert: "2014-06-21 22:44:56"
}
],
count: 2
}
........
.........
}
basically i'm looking to merge the result of the pipeline match stage with the documents of the certifications lookup, so that i can use both. any pointers would be greatly appreciated in formulation the aggregation.
Thank you
Upvotes: 1
Views: 72
Reputation: 36094
$unwind
deconstruct certs
array$lookup
with certifications
pass certifications.certs.itemID
as localField and itemID
as foreignField and result as certification
$unwind
deconstruct result from lookup and in certification
$group
by _id
and reconstruct certs
array and push your required fields after merging using $mergeObjects
, get count using $sum
db.users.aggregate([
{ $unwind: "$certifications.certs" },
{
$lookup: {
from: "certifications",
localField: "certifications.certs.itemID",
foreignField: "itemID",
as: "certification"
}
},
{ $unwind: "$certification" },
{
$group: {
_id: "$_id",
certs: {
$push: {
$mergeObjects: [
"$certifications.certs",
{
country: "$certification.country",
description: "$certification.name.key1"
}
]
}
},
count: { $sum: 1 }
}
}
])
Second approach without $unwind and $group, this may cause performance and speed issues,
$lookup
with certifications
collection$map
to iterate loop of certifications.certs
array$reduce
to iterate loop of certification
, check condition of itemID
and it will return specific field,$map
, merge current object and return object from $reduce
using $mergeObjects
certs
using $size`db.users.aggregate([
{
$lookup: {
from: "certifications",
localField: "certifications.certs.itemID",
foreignField: "itemID",
as: "certification"
}
},
{
$addFields: {
"certification": "$$REMOVE",
"certifications.certs": {
$map: {
input: "$certifications.certs",
as: "c",
in: {
$mergeObjects: [
"$$c",
{
$reduce: {
input: "$certification",
initialValue: {},
in: {
$cond: [
{ $eq: ["$$this.itemID", "$$c.itemID"] },
{
country: "$$this.country",
description: "$$this.name.key1"
},
"$$value"
]
}
}
}
]
}
}
},
"certifications.count": { $size: "$certifications.certs" }
}
}
])
Upvotes: 1