Aggregate result group objects - mongodb

Where I arrived was this I needed to put the user data on the athele:
{
"_id" : ObjectId("5963c6aa1aaf2c1c702ea86f"),
"updatedAt" : ISODate("2017-07-10T18:25:46.941+0000"),
"createdAt" : ISODate("2017-07-10T18:25:46.933+0000"),
"name" : "athleta01",
"nickname" : "01",
"email" : "aaaa#terra.com.br",
"birthday" : ISODate("1986-09-15T03:00:00.000+0000"),
"gender" : "0",
"disable" : false,
"deletedAt" : false,
"profile" : [
{
"departament" : ObjectId("5963c6281aaf2c1c702ea86c"),
"profession" : "athlete",
"_id" : ObjectId("5963c6aa1aaf2c1c702ea870")
}
],
"photo" : null,
"__v" : NumberInt(0)
}
doc Athlete:
{
"_id" : ObjectId("5963c6aa1aaf2c1c702ea871"),
"updatedAt" : ISODate("2017-07-10T19:53:08.285+0000"),
"createdAt" : ISODate("2017-07-10T18:25:46.948+0000"),
"position" : "atacante",
"shirt" : NumberInt(15),
"document" : "87956421345",
"weight" : "10.5",
"height" : "2.73",
"profileId" : ObjectId("5963c6aa1aaf2c1c702ea870"),
"disable" : false,
"deletedAt" : false,
"device" : {
"activityLevel" : "vai atuazliar",
"maxHeartRate" : NumberInt(45),
"reposeHeartRate" : NumberInt(90),
"codSensor" : "1a2s4e1s"
},
"__v" : NumberInt(0)
}
Already tried to make the exit with the project and to set up a group also I did not have the result that I expected. I think I'm missing out on some point.
db.users.aggregate(
[
{
$match: {
"profile.departament" : ObjectId("5963c6281aaf2c1c702ea86c")
}
},
{
$lookup: {
"from" : "institution",
"localField" : "profile.departament",
"foreignField" : "departament._id",
"as" : "user_departament"
}
},
{
$lookup: {
"from" : "athlete",
"localField" : "profile._id",
"foreignField" : "profileId",
"as" : "athlete_departament"
}
},
{
$unwind: {
path: "$athlete_departament",
preserveNullAndEmptyArrays: true
}
},
{
$lookup: {
from: "users",
localField: "athlete_departament.profileId",
foreignField: "profile._id",
as: "username",
}
},
{
$group: {
_id: { name: "$user_departament.name", cnpj: "$user_departament.cnpj", photo: "$user_departament.photo"},
departaments: {
$push : "$user_departament.departament"
},
athletes: {
$push : '$athlete_departament',
}
}
},
{$unwind : "$departaments"},
{$unwind : "$departaments"},
{$unwind : "$_id.name"},
{$unwind : "$_id.cnpj"},
{$unwind : "$_id.photo"},
{$unwind : "$athletes"},
{$unwind : "$athletes"},
{
$group : {
_id : "$_id",
departaments : {$addToSet : "$departaments"},
athletes : {$addToSet : "$athletes"}
}
},
{ "$project": {
//_id : { name: "$_id", departaments: { $concatArrays: [ {$arrayElemAt: [ "$departaments", 0 ]}, "$profiles", "$athletes" ] }}
_id : { institution: "$_id", departaments: { info: "$departaments", profiles: "$profiles", athletes: { username: "$username", athlete: "$athletes" }, }}
//_id : { name: "$_id", departaments: { "departament": { $concatArrays: [ { $arrayElemAt: ["$departaments", 0]}, "$athletes" ] }}}
//_id : { name: "$_id", departaments: { $concatArrays: [ {$arrayElemAt: [ "$departaments", 0 ]}, "$profiles", "$athletes" ] }}
}},
{$unwind : "$_id.departaments.info"},
{$unwind : "$_id.departaments.info"}
]);

Related

Mongodb Aggregation get Data per user

Report table sample data
{
"_id" : ObjectId("614415f4a6566a001623b622"),
"record" : [
{
"dateTime" : ISODate("2021-09-17T04:13:39.465Z"),
"status" : "time-in",
"month" : 9,
"day" : 17,
"year" : 2021,
"time" : 1631852019465.0,
"date" : ISODate("2021-09-17T00:00:00.000Z"),
},
{
"dateTime" : ISODate("2021-09-17T04:14:01.182Z"),
"status" : "time-out",
"month" : 9,
"day" : 17,
"year" : 2021,
"time" : 1631852041182.0,
"date" : ISODate("2021-09-17T00:00:00.000Z"),
}
],
"uid" : ObjectId("614415b0a6566a001623b80b"),
"date" : ISODate("2021-09-17T00:00:00.000Z"),
"status" : "time-out",
"createdAt" : ISODate("2021-09-17T04:13:40.102Z"),
"updatedAt" : ISODate("2021-09-17T04:14:01.831Z"),
"__v" : 0
}
Users table sample data
{
"_id" : ObjectId("615c0f6db30aff375cd05ac1"),
"displayName" : "test test",
"firstName" : "test",
"lastName" : "test",
"email" : "test#gmail.com",
"brand" : "Jollibee",
"phone" : "+632312312312312",
"role" : 1,
"isVerified" : true,
"isArchived" : false,
"createdAt" : ISODate("2021-10-05T08:40:13.208Z"),
"updatedAt" : ISODate("2021-10-05T08:40:13.208Z"),
"__v" : 0
}
I have a data like this
db.getCollection('users').aggregate([
{
"$match": { brand: "Jollibee" }
},
{
$lookup: {
from: "orders",
let: { id: 'id' },
pipeline: [
{
$match: {
date: { $gte: ISODate("2020-11-01"), $lt: ISODate("2021-11-31") },
}
}
],
as: "orders",
},
},
{
$project: {
"_id": 1,
"name": 1,
"orders": 1
}
}
])
when I'm using this aggregation I'm getting all the data inserted per user.
What I want to happen is that. I will only get the data that belong to the user and not all the data of all users.
Added the sample documents for each collection
You are not comparing the userIds of both collections. You should add that on your $match. Playground
db.users.aggregate([
{
"$match": {
brand: "Jollibee"
}
},
{
$lookup: {
from: "orders",
let: {
id: "$_id"
},
pipeline: [
{
$match: {
date: {
$gte: ISODate("2020-11-01"),
$lt: ISODate("2021-11-30")
},
$expr: {
$eq: [
"$uid",
"$$id"
]
}
}
}
],
as: "orders",
},
},
{
$project: {
"_id": 1,
"name": 1,
"orders": 1
}
}
])

What wrong with my mongo query to get a specific by nest document?

{
"_id" : ObjectId("5dbdacc28cffef0b94580dbd"),
"owner" : {
"image" : "https://lh3.googleusercontent.com/a-/AAuE7mCpG2jzbEdffPgdeVWnkBKwyzCCwEB1HMbU1LAVAg=s50",
"fullname" : "soeng kanel",
"userID" : "5da85558886aee13e4e7f044"
},
"image" : "soeng kanel-1572711618984.png",
"body" : "sdadadasdsadadas sds",
"date" : ISODate("2019-11-02T16:20:05.558Z"),
"comments" : [
{
"user" : "5da85558886aee13e4e7f044",
"fullname" : "soeng kanel",
"username" : "",
"comment" : "sdsfdsfdsfds",
"_id" : ObjectId("5dbdacc78cffef0b94580dbf"),
"replies" : [
{
"likes" : [
"5da85558886aee13e4e7f044"
],
"date" : ISODate("2019-11-02T16:20:05.558Z"),
"_id" : ObjectId("5dbdacd78cffef0b94580dc0"),
"reply" : "r1111111",
"username" : "",
"fullname" : "soeng kanel",
"user" : "5da85558886aee13e4e7f044"
},
{
"likes" : [],
"date" : ISODate("2019-11-02T16:20:05.558Z"),
"_id" : ObjectId("5dbdacdb8cffef0b94580dc1"),
"reply" : "r222222",
"username" : "",
"fullname" : "soeng kanel",
"user" : "5da85558886aee13e4e7f044"
},
{
"likes" : [],
"date" : ISODate("2019-11-03T03:04:23.528Z"),
"_id" : ObjectId("5dbe4749fa751f05afcc1bd6"),
"reply" : "33333333",
"username" : "",
"fullname" : "soeng kanel",
"user" : "5da85558886aee13e4e7f044"
}
],
"date" : ISODate("2019-11-02T16:20:05.558Z"),
"likes" : []
}
],
"likes" : [
"5da85558886aee13e4e7f044"
],
"project" : {},
"__v" : 2
}
My query is
db.getCollection("posts").aggregate([
{ $match: {_id: ObjectId("5dbdacc28cffef0b94580dbd"), "comments._id": ObjectId("5dbdacc78cffef0b94580dbf") }},
{ $unwind: "$comments"},
{ $match: { "comments._id": ObjectId("5dbdacc78cffef0b94580dbf")}},
{ $project: {"replies": "$comments.replies", _id: 0}},
{ $match: { "replies._id": ObjectId("5dbdacd78cffef0b94580dc0")}},
{ $project: {"likes": "$replies.likes", _id: 0}},
])
With this query I get 3 elements ,
{
"likes" : [
[
"5da85558886aee13e4e7f044"
],
[],
[]
]
}
That is not what I want, what I want is to get by specific
replies by this _id 5dbdacd78cffef0b94580dc0.
And My expectation
{
"likes" : [
[
"5da85558886aee13e4e7f044"
]
]
}
Try using $unwind on replies before you $match stage on replies.
db.collection.aggregate([
{
$match: {
_id: ObjectId("5dbdacc28cffef0b94580dbd"),
"comments._id": ObjectId("5dbdacc78cffef0b94580dbf")
}
},
{
$unwind: {
path: "$comments",
preserveNullAndEmptyArrays: false
}
},
{
$match: {
"comments._id": ObjectId("5dbdacc78cffef0b94580dbf")
}
},
{
$project: {
"replies": "$comments.replies",
_id: 0
}
},
{
$unwind: {
path: "$replies",
preserveNullAndEmptyArrays: false
}
},
{
$match: {
"replies._id": ObjectId("5dbdacd78cffef0b94580dc0")
}
},
{
$project: {
"likes": "$replies.likes"
}
}
])
Above query produce output in the following fashion:
[
{
"likes": [
"5da85558886aee13e4e7f044"
]
}
]
I hope that's okay.

Nested lookup in mongo db query

I am making a airline dummy webside, and i need get all sold tickets per flight for all airlines, i have 3 collections: airlines, flights and sales
I tried using a nested lookups in mongodb query, but i cant sum the total tickets, here is the current query and the result:
Airline.aggregate([{
$lookup: {
from: "flights",
localField: "id_airline",
foreignField: "id_airline",
as: "flights"
}
}, {
$unwind: {
path: "$flights",
preserveNullAndEmptyArrays: true
}
}, {
$lookup: {
from: "sales",
localField: "flights.id_flight",
foreignField: "id_flight",
as: "flights.sales",
}
}, {
$group: {
_id : "$_id",
idAirline: { $first: "$id_airline" },
flights: { $push: "$flights" }
}
}, {
$project: {
_id: 1,
idAirline: 1,
"flights.id_flight": 1,
"flights.price": 1,
"flights.sold":{$sum:"$flights.sales.tickets"}
}
}]
And the result is:
... },
{
"_id": "5db381cb18518043c40e3ecd",
"idAirline": "AVI-242",
"flights": [
{
"id_flight": "CPA-001",
"price": "125",
"sold": 0
},
{
"id_flight": "CGA-002",
"price": "150",
"sold": 0
},
{
"id_flight": "CHA-003",
"price": "135",
"sold": 0
}
]
},
....
Actually the fligth CPA-001 has 6 tickets sold but i cant sum a get the result.
Here are the documents:
Airlines
{"_id":{"$oid":"5db3823718518043c40e3ece"},"country":["Panamá","El Salvador","Belice"],"id_airline":"VOL-643","name_airport":"Juan Santamaría","name_airline":"Volaris","createdAt":{"$date":{"$numberLong":"1572045367094"}},"updatedAt":{"$date":{"$numberLong":"1572045367094"}},"__v":{"$numberInt":"0"}}
Flights
{"_id":{"$oid":"5db9a225154a1b1b08cc77c3"},"restrictions":["No Liquids"],"features":[],"id_flight":"CPA-001","id_airline":"AVI-242","date_departure":{"$date":{"$numberLong":"1546300800000"}},"date_arrival":{"$date":{"$numberLong":"1559779200000"}},"name":"CosPan","origin":"Costa Rica","destination":"Panamá","itinerary":"50 breakfasts","price":"125","status":"On Time","max_capacity":"50","createdAt":{"$date":{"$numberLong":"1572446757327"}},"updatedAt":{"$date":{"$numberLong":"1572447464367"}},"__v":{"$numberInt":"0"}}
Sales
{"_id":{"$oid":"5db9b643b50c0d1540b8db89"},"id_user":"304780391","id_flight":"CPA-001","origin":"Costa Rica","destination":"Panamá","date_departure":{"$date":{"$numberLong":"1546300800000"}},"date_arrival":{"$date":{"$numberLong":"1559779200000"}},"tickets":{"$numberInt":"4"},"suitcases":{"$numberInt":"1"},"status":"Bought","seat":{"$numberInt":"-1"},"createdAt":{"$date":{"$numberLong":"1572451907375"}},"updatedAt":{"$date":{"$numberLong":"1572451907375"}},"__v":{"$numberInt":"0"}}
I think the nested arrays are causing some difficulties. I added another $unwind between $lookup and $group. Let me know what you think...
db.airlines.aggregate([
{ $lookup: {
from: "flights",
localField: "id_airline",
foreignField: "id_airline",
as: "flights"
}
},
{ $unwind: {
path: "$flights",
preserveNullAndEmptyArrays: true
}
},
{ $lookup: {
from: "sales",
localField: "flights.id_flight",
foreignField: "id_flight",
as: "flights.sales",
}
},
{ $unwind: {
path: "$flights.sales",
preserveNullAndEmptyArrays: true
}
},
{ $group: {
_id : "$_id",
idAirline: { $first: "$id_airline" },
flights: { $push: "$flights" }
}
},
{ $project: {
_id: 1,
idAirline: 1,
"flights.id_flight": 1,
"flights.price": 1,
"flights.sold":{$sum: "$flights.sales.tickets"}
}
}
]).pretty()
Documents used to test:
flights
{
"_id" : ObjectId("5db9a225154a1b1b08cc77c3"),
"restrictions" : [
"No Liquids"
],
"features" : [ ],
"id_flight" : "CPA-001",
"id_airline" : "VOL-643",
"date_departure" : ISODate("2019-10-30T23:04:17.119Z"),
"date_arrival" : ISODate("2019-10-30T23:04:17.119Z"),
"name" : "CosPan",
"origin" : "Costa Rica",
"destination" : "Panamá",
"itinerary" : "50 breakfasts",
"price" : "125",
"status" : "On Time",
"max_capacity" : "50",
"createdAt" : ISODate("2019-10-30T23:04:17.119Z"),
"updatedAt" : ISODate("2019-10-30T23:04:17.119Z"),
"__v" : {
"$numberInt" : "0"
}
}
airlines
{
"_id" : ObjectId("5db3823718518043c40e3ece"),
"country" : [
"Panamá",
"El Salvador",
"Belice"
],
"id_airline" : "VOL-643",
"name_airport" : "Juan Santamaría",
"name_airline" : "Volaris",
"createdAt" : ISODate("2019-10-30T23:04:17.119Z"),
"updatedAt" : ISODate("2019-10-30T23:04:17.119Z"),
"__v" : {
"$numberInt" : "0"
}
}
sales
[{
"_id" : ObjectId("5db9b643b50c0d1540b8db89"),
"id_user" : "304780391",
"id_flight" : "CPA-001",
"origin" : "Costa Rica",
"destination" : "Panamá",
"date_departure" : ISODate("2019-10-30T23:04:17.119Z"),
"date_arrival" : ISODate("2019-10-30T23:04:17.119Z"),
"tickets" : 4,
"suitcases" : {
"$numberInt" : "1"
},
"status" : "Bought",
"seat" : -1,
"createdAt" : ISODate("2019-10-30T23:04:17.119Z"),
"updatedAt" : ISODate("2019-10-30T23:04:17.119Z"),
"__v" : {
"$numberInt" : "0"
}
},
{
"_id" : ObjectId("5db9b643b50c0d1540b8db8a"),
"id_user" : "304780391",
"id_flight" : "CPA-001",
"origin" : "Costa Rica",
"destination" : "Panamá",
"date_departure" : ISODate("2019-10-30T23:04:17.119Z"),
"date_arrival" : ISODate("2019-10-30T23:04:17.119Z"),
"tickets" : 4,
"suitcases" : {
"$numberInt" : "1"
},
"status" : "Bought",
"seat" : -1,
"createdAt" : ISODate("2019-10-30T23:04:17.119Z"),
"updatedAt" : ISODate("2019-10-30T23:04:17.119Z"),
"__v" : {
"$numberInt" : "0"
}
}]

Mongodb $lookup joins all collection instead of matching object

so I am trying to do a $lookup with Mongodb but I have a strange output.
I have two collections, "sites" and "consumptions".
sites :
{
"_id" : ObjectId("5b26db6e7f59e825909da106"),
"siteId" : 49,
"industry" : "Commercial Property",
"sub_industry" : "Shopping Center/Shopping Mall",
"square_feet" : 497092,
"latitude" : 41.2161756,
"longitude" : -78.14809154,
"timezone" : "America/New_York",
"timezone_offset" : "-04:00",
"__v" : 0
}
consumptions :
{
"_id" : ObjectId("5b26db907f59e825909f3d2a"),
"timestamp" : 1325382000,
"dttm_utc" : ISODate("2012-01-01T00:40:00Z"),
"value" : 2.8956,
"estimated" : 0,
"anomaly" : "",
"site" : [
{
"_id" : ObjectId("5b26db727f59e825909da16a")
}
],
"__v" : 0
}
This is the $lookup I am trying to do :
db.consumptions.aggregate([
{
$lookup:
{
from: "sites",
localField: "site.id",
foreignField: "id",
as: "site"
}
}
])
The expected output would be to have the detail of the site in each consumption :
{
"_id" : ObjectId("5b26db907f59e825909f3d2a"),
"timestamp" : 1325382000,
"dttm_utc" : ISODate("2012-01-01T00:40:00Z"),
"value" : 2.8956,
"estimated" : 0,
"anomaly" : "",
"site" : [
{
"_id" : ObjectId("5b26db6e7f59e825909da106"),
"siteId" : 49,
"industry" : "Commercial Property",
"sub_industry" : "Shopping Center/Shopping Mall",
"square_feet" : 497092,
"latitude" : 41.2161756,
"longitude" : -78.14809154,
"timezone" : "America/New_York",
"timezone_offset" : "-04:00",
"__v" : 0
}
],
"__v" : 0
}
This is the output I am getting with the $lookup :
{
"_id" : ObjectId("5b26db907f59e825909f3d2a"),
"timestamp" : 1325382000,
"dttm_utc" : ISODate("2012-01-01T00:40:00Z"),
"value" : 2.8956,
"estimated" : 0,
"anomaly" : "",
"site" : [
{
"_id" : ObjectId("5b26db6e7f59e825909da0f3"),
"siteId" : 6,
"industry" : "Commercial Property",
"sub_industry" : "Shopping Center/Shopping Mall",
"square_feet" : 161532,
"latitude" : 34.78300117,
"longitude" : -106.8952497,
"timezone" : "America/Denver",
"timezone_offset" : "-06:00",
"__v" : 0
},
{
"_id" : ObjectId("5b26db6e7f59e825909da0f4"),
"siteId" : 8,
"industry" : "Commercial Property",
"sub_industry" : "Shopping Center/Shopping Mall",
"square_feet" : 823966,
"latitude" : 40.32024733,
"longitude" : -76.40494239,
"timezone" : "America/New_York",
"timezone_offset" : "-04:00",
"__v" : 0
}, ... (all the sites details are listed)
],
"__v" : 0
}
Thank you in advance for your help !
You need to first $unwind the site array to match site._id to the foreign field _id and then $group to rolling back into the arrays again.
db.collection.aggregate([
{ "$unwind": "$site" },
{ "$lookup": {
"from": Site.collection.name,
"localField": "site._id",
"foreignField": "_id",
"as": "site"
}},
{ "$unwind": "$site" },
{ "$group": {
"_id": "$_id",
"value": { "$first": "$value" },
"estimated": { "$first": "$estimated" },
"anomaly": { "$first": "$anomaly" },
"timestamp": { "$first": "$timestamp" },
"dttm_utc": { "$first": "$dttm_utc" },
"site": { "$push": "$site" }
}}
])
And if you have mongodb 3.6 then you can try this
db.collection.aggregate([
{ "$unwind": "$site" },
{ "$lookup": {
"from": Site.collection.name,
"let": { "siteId": "$site._id" },
"pipeline": [
{ "$match": { "$expr": { "$eq": [ "$_id", "$$siteId" ] } } }
],
"as": "site"
}},
{ "$unwind": "$site" },
{ "$group": {
"_id": "$_id",
"value": { "$first": "$value" },
"estimated": { "$first": "$estimated" },
"anomaly": { "$first": "$anomaly" },
"timestamp": { "$first": "$timestamp" },
"dttm_utc": { "$first": "$dttm_utc" },
"site": { "$push": "$site" }
}}
])
Make sure you should put Site.collection.name correctly
I think that The $lookup doesn't work directly with an array.
try using $unwind first.

Mongodb aggregation retrieving document from inside of document

I have problems with MongoDB's aggregation.
In my "Job" document, it has creatorParent(single value) and Children(array of mongodb object id). In the "User" document, user has children array with child details.
When user request for retrieving this document I want aggregate child details, if array contains id of child.
I wrote an aggregation with some help, It worked for creatorParent but whatever I've tried, it didn't worked for children.
db.getCollection('Jobs').aggregate([
{
$unwind: {
path : "$children"
}
},
{
$lookup: {
"from" : "Users",
"localField" : "creatorparent",
"foreignField" : "_id",
"as" : "creatorparent"
}
},
{
$lookup: {
"from" : "Users",
"localField" : "children",
"foreignField" : "children",
"as" : "children"
}
}
])
Users document:
{
"_id" : ObjectId("58daf84877733645eaa9b44f"),
"email" : "meto93#gmail.com",
"password" : "vpGl+Fjnef616cRgNbCkwaFDpSI=",
"passwordsalt" : "99397F4A9D3A499D96694547667E74595CE994D2E83345D6953EF866303E8B65",
"children" : [
{
"_id" : ObjectId("58daf84977733645eaa9b450"),
"name" : "Mert",
"age" : 5,
"additionalinformation" : "ilk cocuk",
"creationtime" : ISODate("2017-03-28T23:56:56.952Z"),
"userid" : ObjectId("58daf84877733645eaa9b44f"),
"gender" : null
},
{
"_id" : ObjectId("58daf84977733645eaa9b451"),
"name" : "Sencer",
"age" : 7,
"additionalinformation" : "ikinci cocuk",
"creationtime" : ISODate("2017-03-28T23:56:56.952Z"),
"userid" : ObjectId("58daf84877733645eaa9b44f"),
"gender" : null
}
]
}
Job
{
"_id" : ObjectId("58db0a2d77733645eaa9b453"),
"creationtime" : ISODate("2017-03-29T01:13:17.509Z"),
"startingtime" : ISODate("2017-04-03T13:00:00.000Z"),
"endingtime" : ISODate("2017-04-03T17:00:00.000Z"),
"children" : [
ObjectId("58daf84977733645eaa9b450"),
ObjectId("58daf84977733645eaa9b451")
],
"creatorparent" : ObjectId("58daf84877733645eaa9b44f"),
"applicants" : []
}
Try this:
db.jobs.aggregate(
[
{
$unwind: {
path : "$children",
}
},
{
$lookup: {
"from" : "users",
"localField" : "creatorparent",
"foreignField" : "_id",
"as" : "creatorparent"
}
},
{
$lookup: {
"from" : "users",
"localField" : "children",
"foreignField" : "children._id",
"as" : "children"
}
},
{
$addFields: {
children : {$arrayElemAt : ["$children",0]}
}
},
{
$addFields: {
"children":"$children.children"
}
},
{
$unwind: {
path : "$children",
}
},
{
$group: {
"_id": "$_id",
"name": { "$first": "$name" },
"jobstatus" : { "$first": "$jobstatus" },
"hourlyrate" : { "$first": "$hourlyrate" },
"creatorparent" : { "$first" : "$creatorparent" },
"children": { "$addToSet": "$children" }
}
},
]
);