How to group an array by same value from different collections in Mongo aggregation - mongodb

I need to group at an array named location by the same coordinates field from both engagements and broadcastreports. Also if one coordinate exist in one but not on the other, It should be included anyway.
In that array I need to include a scans which is the number of engagements related to a campaign_ad_group and a impressions field which is the sum of broadcastreports.analytics.impressions related also to a campaign_ad_group.
I have the following aggregation:
.aggregate([
{
$match: {
'_id': ObjectId("60520e1d09ba3a769ab85f68"),
}
},
{
$project: {
'_id': 1,
'broadcasts_to': 1
}
},
{
$lookup: {
from: 'campaignadgroups',
localField: '_id',
foreignField: 'campaign_id',
as:'campaign_ad_group'
}
},
{
$unwind: '$campaign_ad_group'
},
{
$lookup: {
from: 'broadcastplans',
let: { 'campaign_ad_group_id': '$campaign_ad_group._id' },
as: 'broadcastplans',
pipeline: [
{
$match: {
$expr: {
$eq: ['$campaign_ad_group_id','$$campaign_ad_group_id' ]
}
}
},
{ $project: { '_id': 1 } }
]
}
},
// Above it's only the necessary data gathering to get the needed engagements and broadcastreports.
{
$lookup: {
from: 'engagements',
let: { 'broadcastplan_ids': '$broadcastplans._id' },
as: 'engagements',
pipeline: [
{
$match: {
$expr: {
$and: [
{ $in: ['$broadcast_plan_id', '$$broadcastplan_ids'] },
{ $gte: ['$reported_at', ISODate('2019-12-29T15:02:47.305Z')] },
{ $lte: ['$reported_at', ISODate('2021-12-29T15:02:47.305Z')] }
]
}
}
}
]
}
},
{
$unwind: '$engagements'
},
{
$group: {
'_id': {
'adgroup_id': '$campaign_ad_group._id',
'coordinates': '$engagements.location.coordinates',
},
'adgroup_name': {$first: '$campaign_ad_group.name'},
'scans': {$sum: 1}
}
},
{
$group: {
'_id': '$_id.adgroup_id',
'name': {$first: '$adgroup_name'},
'location': {
$push: {
'scans': '$scans',
'coordinates': '$_id.coordinates'
}
}
}
}
])
The output I get is the following:
{
"_id" : ObjectId("5fe9f89f603eaa22b3d374f5"),
"name" : "Sick name",
"location" : [
{
"scans" : 1.0,
"coordinates" : [
-8.63294964028813,
56.1520268933931
]
},
{
"scans" : 1.0,
"coordinates" : [
-9.63294964028813,
58.1520268933931
]
}
]
}
Now it comes the part that I'm stuck at. I need to look up for the collection broadcastreports and group by its coordinates with the engagements coordinates and include a field impressions which is the sum of broadcastreports.analytics.impressions.
By removing the group pipeline and lookup from the broadcastreports it will look like so:
.aggregate([
.
. // ABOVE IS THE SAME DATA GATHERING AS BEFORE
.
{
$lookup: {
from: 'engagements',
let: { 'broadcastplan_ids': '$broadcastplans._id' },
as: 'engagements',
pipeline: [
{
$match: {
$expr: {
$and: [
{ $in: ['$broadcast_plan_id', '$$broadcastplan_ids'] },
{ $gte: ['$reported_at', ISODate('2019-12-29T15:02:47.305Z')] },
{ $lte: ['$reported_at', ISODate('2021-12-29T15:02:47.305Z')] }
]
}
}
}
]
}
},
{
$lookup: {
from: 'broadcastreports',
let: { 'broadcastplan_ids': '$broadcastplans._id' },
as: 'broadcastreports',
pipeline: [
{
$match: {
$expr: {
$and: [
{ $in: ['$broadcast_plan_id', '$$broadcastplan_ids'] },
{ $gte: ['$reported_at', ISODate('2019-12-29T15:02:47.305Z')] },
{ $lte: ['$reported_at', ISODate('2021-12-29T15:02:47.305Z')] }
]
}
}
}
]
}
},
])
This gets me all the data I need which is something like:
{
_id: ObjectId("60520e1d09ba3a769ab85f68"),
campaign_ad_group: {
_id: ObjectId("5fc1215a039674c600c0f533"),
name: 'Sick name'
},
broadcastplans: [_ids],
engagements: [
{
_id,
coordinates: [-9.63294964028813,58.1520268933931],
reported_at: Date
},
{
_id,
coordinates: [-8.63294964028813,56.1520268933931],
reported_at: Date
}
],
broadcastreports: [
{
_id,
coordinates: [-9.63294964028813,58.1520268933931],
reported_at: Date,
analytics: {
impressions: 10
}
},
{
_id,
coordinates: [-5.20923334343244,40.4874833434234],
reported_at: Date,
analytics: {
impressions: 5
}
}
]
}
I need to group this in a way that I get the following output:
[
{
_id: campaign_ad_group._id,
name: campaign_ad_group.name,
location: [
{
scans: 1,
impressions: 10,
coordinates: [-9.63294964028813,58.1520268933931]
},
{
scans: 0, // This coordinate does not exist on the engagements so its 0 but needs to be
// included anyway.
impressions: 5,
coordinates: [-5.20923334343244,40.4874833434234]
},
{
scans: 1,
impressions: 0, // Same here
coordinates: [-8.63294964028813,56.1520268933931]
},
]
}
]

Use $unionWith.
Documentation: https://docs.mongodb.com/manual/reference/operator/aggregation/unionWith/

The solution was to make use of unionWith. I did it like so:
.aggregate([
{
$match: {
'_id': ObjectId("60520e1d09ba3a769ab85f68"),
}
},
{
$project: {
'_id': 1,
'broadcasts_to': 1
}
},
{
$lookup: {
from: 'campaignadgroups',
localField: '_id',
foreignField: 'campaign_id',
as:'campaign_ad_group'
}
},
{
$unwind: '$campaign_ad_group'
},
{
$lookup: {
from: 'broadcastplans',
let: { 'campaign_ad_group_id': '$campaign_ad_group._id' },
as: 'broadcastplans',
pipeline: [
{
$match: {
$expr: {
$eq: ['$campaign_ad_group_id','$$campaign_ad_group_id' ]
}
}
},
{ $project: { '_id': 1 } }
]
}
},
// Needed data gathering for the next lookups
{
$lookup: {
from: 'engagements',
let: { 'broadcastplan_ids': '$broadcastplans._id' },
as: 'locations',
pipeline: [
{
$match: {
$expr: {
$and: [
{ $in: ['$broadcast_plan_id', '$$broadcastplan_ids'] },
{ $gte: ['$reported_at', ISODate('2019-12-29T15:02:47.305Z')] },
{ $lte: ['$reported_at', ISODate('2021-12-29T15:02:47.305Z')] }
]
}
}
},
{
$group: {
'_id': '$location.coordinates',
'location': {$first:'$location'},
'scans': {$sum: 1}
}
},
{
$unionWith: {
coll: 'broadcastreports',
pipeline: [
{
$match: {
$expr: {
$and: [
{ $in: ['$broadcast_plan_id', '$$broadcastplan_ids'] },
{ $gte: ['$reported_at', ISODate('2019-12-29T15:02:47.305Z')] },
{ $lte: ['$reported_at', ISODate('2021-12-29T15:02:47.305Z')] }
]
}
}
},
]
}
},
{
$group: {
'_id': '$location.coordinates',
'impressions': {$sum: '$analytics.impressions'},
'scans': {$first: '$scans'}
}
},
{
$project: {
'_id': 0,
'coordinates': '$_id',
'impressions': {$ifNull: ['$impressions', 0]},
'scans': {$ifNull: ['$scans',0]}
}
}
]
}
},
{
$group: {
'_id': '$campaign_ad_group._id',
'name': {$first:'$campaign_ad_group.name'},
'locations': {$first: '$locations'}
}
}
])
The output:
{
"_id" : ObjectId("5fe9f89f603eaa22b3d374f5"),
"name" : "Sick name",
"locations" : [
{
"coordinates" : [
-9.63294964028813,
42.1520268933931
],
"impressions" : 0,
"scans" : 1.0
},
{
"coordinates" : [
-8.63294964028813,
41.1520268933931
],
"impressions" : 0,
"scans" : 1.0
},
{
"coordinates" : [
0,
0
],
"impressions" : 1,
"scans" : 0.0
}
]
}

Related

mongoDB lookups upto 4-5 levels with arrays

I am trying to create aggregate code which can join multiple collections and fetches data based on the condition
My collections looks like the following
Users Collection(Example Document)
{
"_id":{"$oid":"6137038058d4632824c84872"},
"first_name":"test",
"last_name":".",
"email":"valid#gmail.com",
"enrolled_courses":[
{
"completed_lessons":[],
"completed":false,
"_id": {"$oid":"6142d1c76d657428903420db"},
"course_id":{"$oid":"614033510a61aa1f3c8b94ff"}
},
{
"completed_lessons":[],
"completed":false,
"_id":{"$oid":"6156d686dcbc58503c7ec679"},
"course_id":{"$oid":"61486e57460b5a422c6e63ca"}
},
{
"completed_lessons":["616d181e62cb265db07d9273","616d182e62cb265db07d9293"],
"completed":false,
"_id":{"$oid":"616d2424149936380c186c2d"},
"course_id":{"$oid":"616d105662cb265db07d91cf"}
}
]
}
Courses Collection(Example Document)
{
"_id":{"$oid":"6135f735b399f03ba03d74ce"},
"type":1,
"enrolled_users":["61374040c27237b1ed87480b"],
"is_deleted":0,
"status":1,
"company_id":{"$oid":"6135f6c9b399f03ba03d74a0"},
"course":"Course 1"
}
Modules Collection(Example Document)
{
"_id":{"$oid":"616d17fd62cb265db07d9240"},
"type":1,
"is_always_available":false,
"is_deleted":0,
"status":1,
"company_id":{"$oid":"6135f6c9b399f03ba03d74a0"},
"course_id":{"$oid":"616d105662cb265db07d91cf"},
"module_name":"module 3",
"due_date":{"$date":"2021-10-18T00:00:00.000Z"}
}
Lessons Collection(Example Document)
{
"_id":{"$oid":"616d184962cb265db07d92cb"},
"lessson_image":null,
"status":1,
"is_deleted": 0,
"module_id":{"$oid":"616d17e462cb265db07d921f"},
"lessson_name":"Lesson 3"
}
I want to fetch details of all the courses user have enrolled and fetch all course's modules and its lessons
My expected output should be like following -
[
{
//CourseDetail 1 Keys,
modules: [
{
//Module Details
lessons: [{
//lessons of this module
}]
},
{
//Module Details
lessons: [{
//lessons of this module
}]
}
]
},
{
//CourseDetail 2 Keys,
modules: [
{
//Module Details
lessons: [{
//lessons of this module
}]
},
{
//Module Details
lessons: [{
//lessons of this module
}]
}
]
}
]
My current query is following, what it currently does is it groups the modules and its lessons together and bind it to single course object. The fetching of modules and lessons is perfect as per my requirement but course array contains only 1 single object and it holds list of all the modules from other courses also.
Current Query Code
let courseDetails = await users.aggregate([
{
$match: { _id: mongoose.Types.ObjectId(user._id), }
},
{$unwind:"$enrolled_courses"},
{
$lookup: {
from: 'courses',
localField: "enrolled_courses.course_id",
foreignField: "_id",
as: "courseDetails"
}
},
{ $unwind: { path: "$courseDetails", preserveNullAndEmptyArrays: true}},
{
$lookup: {
from: "modules",
let: { currentCourseId: "$courseDetails._id"},
pipeline: [{
$match: {
$expr: {
$and: [
{ $eq: ["$course_id", "$$currentCourseId"]},
{ $eq: ["$status", 1]},
{ $eq: ["$is_deleted", 0]},
{
$or: [
{ $eq: ["$is_always_available", true] },
{ $gte: ["$due_date", convertedDate]}
]
}
]
}
}
},
{
$project: {
_id: 1,
module_name: 1,
company_id: 1,
course_id: 1
}
}],
as: "moduleList"
}
},
{ $unwind: { path: "$moduleList", preserveNullAndEmptyArrays: true }},
{
$lookup: {
from: "lessons",
let: { curentModuleId: "$moduleList._id"},
pipeline: [{
$match: {
$expr: {
$and: [
{ $eq: ["$status", 1] },
{ $eq: ["$is_deleted", 0]},
{ $eq: ["$module_id", "$$curentModuleId"]}
]
}
}
}, {
$project: {
_id: 1,
lessson_name: 1,
module_id: 1
}
}],
as: "moduleList.lessons"
}
},
{
$group: {
_id: "$_id",
course_id: { $first: "$enrolled_courses.course_id"},
course_name: { $first: "$courseDetails.course"},
completed_lessons: { $first: "$enrolled_courses.completed_lessons"},
current_lessons: { $first: "$enrolled_courses.current_lessons"},
completed: { $first: "$enrolled_courses.completed"},
enrolled_users_count: {
$first: "$courseDetails.enrolled_users"
},
modules: {
$push: "$moduleList"
}
}
},
{
$project: {
course_id: 1,
course_name: 1,
completed_lessons: 1,
current_lessons: 1,
completed: 1,
enrolled_users_count: {
$size: "$enrolled_users_count"
},
modules: 1
}
},
{
$group: {
_id: "$_id",
course_id: { $first: "$course_id"},
course_name: { $first: "$course_name"},
completed_lessons: { $first: "$completed_lessons"},
current_lessons: { $first: "$current_lessons"},
completed: { $first: "$completed"},
enrolled_users_count: { $first: "$enrolled_users_count"},
modules: { $first: "$modules"}
}
}
]);

mongodb lookup using multiple fields not working

I am trying to get some other information from titleInfo collection using siteId of regCodes collection
I have two collections
regCodes
{
"siteId" : "123A",
"registration_code" : "ABC",
"used_flag" : true,
"Allowed_Use" : 1,
"Remaining_Use" : 0,
"BatchId" : "SNGL",
"CodeDuration" : 180
}
titleInfo
{
"title" : "Principles of Microeconomics",
"product_form_detail" : "EPUB",
"final_binding_description" : "Ebook",
"vitalsource_enabled" : false,
"reading_line" : "with InQuizitive and Smartwork5",
"volume" : "",
"protected_content" : {
"ebookSiteIds" : [
"123A"
],
"studySpaceSiteIds" : [],
"iqSiteIds" : []
}
}
below query not working, getting 'regcodeData' as empty array.
using mongodb version 3.6.18
db.getCollection('regCodes').aggregate([
{
$match: {
registration_code: 'ABC'
}
},
{
$lookup: {
from: "titleInfo",
let: {
regcode_siteId: "$siteId"
},
pipeline: [
{
$match: {
$expr: {
$or: [
{
$eq: [
"$protected_content.ebookSiteIds",
"$$regcode_siteId"
]
},
{
$eq: [
"$protected_content.studySpaceSiteIds",
"$$regcode_siteId"
]
},
{
$eq: [
"$protected_content.iqSiteIds",
"$$regcode_siteId"
]
}
]
}
}
}
],
as: "regcodeData"
}
}
])
below query is working as expected
db.getCollection('titleInfo').find({
$or: [
{
"protected_content.ebookSiteIds": "123A"
},
{
"protected_content.studySpaceSiteIds": "123A"
},
{
"protected_content.iqSiteIds": "123A"
}
]
})
You just need to unwind the arrays, by using $unwind operator with preserveNullAndEmptyArrays option set to true.
Updated Query:
db.regCodes.aggregate([
{
$match: {
registration_code: "ABC"
}
},
{
$lookup: {
from: "titleInfo",
let: {
regcode_siteId: "$siteId"
},
pipeline: [
{
$unwind: {
path: "$protected_content.ebookSiteIds",
preserveNullAndEmptyArrays: true
}
},
{
$unwind: {
path: "$protected_content.studySpaceSiteIds",
preserveNullAndEmptyArrays: true
}
},
{
$unwind: {
path: "$protected_content.iqSiteIds",
preserveNullAndEmptyArrays: true
}
},
{
$match: {
$expr: {
$or: [
{
$eq: [
"$protected_content.ebookSiteIds",
"$$regcode_siteId"
]
},
{
$eq: [
"$protected_content.studySpaceSiteIds",
"$$regcode_siteId"
]
},
{
$eq: [
"$protected_content.iqSiteIds",
"$$regcode_siteId"
]
}
]
}
}
}
],
as: "regcodeData"
}
}
])
MongoPlayGroundLink
My bad trying to match array with string
Answer is as below
db.getCollection('regCodes').aggregate([
{
$match: {
registration_code: 'ABC'
}
},
{
$lookup: {
from: "titleInfo",
let: {
regcode_siteId: "$siteId"
},
pipeline: [
{
$match: {
$expr: {
$or: [
{
$in: [
"$$regcode_siteId",
"$protected_content.ebookSiteIds"
]
},
{
$in: [
"$$regcode_siteId",
"$protected_content.studySpaceSiteIds"
]
},
{
$in: [
"$$regcode_siteId",
"$protected_content.iqSiteIds"
]
}
]
}
}
}
],
as: "regcodeData"
}
}
])

how to use $groupby and transform distinct value mongodb

How to transform the data using $if $else groupby condition MongoDB?
This playground should return two object who belongs to text with "tester 2" and "tester 3" also if I have multiple object in history collection it should also check with last object not will all object how it is possible
So condition should say if history's date is $gt then main collection should return nothing else return the matched criteria data.
db.main.aggregate([
{
$lookup: {
from: "history",
localField: "history_id",
foreignField: "history_id",
as: "History"
}
},
{
$unwind: "$History"
},
{
"$match": {
$expr: {
$cond: {
if: {
$eq: [
"5e4e74eb380054797d9db623",
"$History.user_id"
]
},
then: {
$and: [
{
$gt: [
"$date",
"$History.date"
]
},
{
$eq: [
"5e4e74eb380054797d9db623",
"$History.user_id"
]
}
]
},
else: {}
}
}
}
}
])
MongoPlayground
If I understand you correctly, it is what you are trying to do:
db.main.aggregate([
{
$lookup: {
from: "history",
let: {
main_history_id: "$history_id",
main_user_id: { $toString: "$sender_id" }
},
pipeline: [
{
$match: {
$expr: {
$and: [
{
$eq: [
"$history_id",
"$$main_history_id"
]
},
{
$eq: [
"$user_id",
"$$main_user_id"
]
}
]
}
}
}
],
as: "History"
}
},
{
$unwind: {
path: "$History",
preserveNullAndEmptyArrays: true
}
},
{
$sort: {
_id: 1,
"History.history_id": 1,
"History.date": 1
}
},
{
$group: {
_id: "$_id",
data: { $last: "$$ROOT" },
History: { $last: "$History" }
}
},
{
$replaceRoot: {
newRoot: {
$mergeObjects: [
"$data",
{ History: "$History" }
]
}
}
},
{
"$match": {
$expr: {
$or: [
{
$eq: [
{ $type: "$History.date" },
"missing"
]
},
{
$ne: [
"5e4e74eb380054797d9db623",
"$History.user_id"
]
},
{
$and: [
{
$eq: [
"5e4e74eb380054797d9db623",
"$History.user_id"
]
},
{
$gte: [
"$date",
"$History.date"
]
}
]
}
]
}
}
}
])
MongoPlayground

MongoDB - group by on facet result

Provided I have following collections
Customers
[
{
uuid: "first",
culture: "it-it"
},
{
uuid: "second",
culture: "de-de"
}
]
Vehicles
[
{
model: "mymodel",
users: [
{
uuid: "first",
isOwner: true,
createdOn: "2019-05-15T06: 00: 00"
}
]
},
{
model: "mymodel",
users: [
{
uuid: "first",
isOwner: false,
createdOn: "2019-05-15T06: 00: 00"
},
{
uuid: "second",
isOwner: true,
createdOn: "2019-05-15T06: 00: 00"
}
]
}
]
And following query:
db.customers.aggregate([
{
$lookup: {
from: "vehicles",
let: {
uuid: "$uuid"
},
pipeline: [
{
$match: {
$expr: {
$in: [
"$$uuid",
"$users.uuid"
]
}
}
},
{
$project: {
model: 1,
users: {
$filter: {
input: "$users",
as: "user",
cond: {
$eq: [
"$$user.uuid",
"$$uuid"
]
}
}
}
}
},
{
$unwind: "$users"
},
{
$replaceRoot: {
newRoot: {
isOwner: "$users.isOwner",
createdOn: "$users.createdOn"
}
}
}
],
as: "vehicles"
}
},
{
$facet: {
"createdOn": [
{
$match: {
"vehicles": {
$elemMatch: {
isOwner: true,
$and: [
{
"createdOn": {
$gte: "2019-05-15T00: 00: 00"
}
},
{
"createdOn": {
$lt: "2019-05-16T00: 00: 00"
}
}
]
}
}
}
},
{
$project: {
culture: 1,
count: {
$size: "$vehicles"
}
}
},
{
$group: {
_id: 0,
"total": {
$sum: "$count"
}
}
}
]
}
},
{
$project: {
"CreatedOn": {
$arrayElemAt: [
"$CreatedOn.total",
0
]
}
}
}
])
I get following result:
[
{
"createdOn": 2
}
]
What I would like to achieve is a result as follows:
[
{
culture: "it-it",
results: {
"createdOn": 1
}
},
{
culture: "de-de",
results: {
"createdOn": 1
}
}
]
But I cannot seem to figure out where I can group so that I can get that result.
Can someone show me the way to do this?
The query is more complex with more metrics so this is a trimmed down version of what I have.
I tried grouping everywhere but fail to get the desired result I want.
The following query can get us the expected output:
db.customers.aggregate([
{
$lookup: {
"from": "vehicles",
"let": {
"uuid": "$uuid"
},
"pipeline": [
{
$unwind: "$users"
},
{
$match: {
$expr: {
$and: [
{
$eq: ["$users.uuid", "$$uuid"]
},
{
$eq: ["$users.isOwner", true]
},
{
$gte: ["$users.createdOn", "2019-05-15T00: 00: 00"]
},
{
$lte: ["$users.createdOn", "2019-05-16T00: 00: 00"]
}
]
}
}
},
{
$count:"totalVehicles"
}
],
as: "vehiclesInfo"
}
},
{
$unwind: {
"path": "$vehiclesInfo",
"preserveNullAndEmptyArrays": true
}
},
{
$group: {
"_id": "$culture",
"culture": {
$first: "$culture"
},
"createdOn": {
$sum: "$vehiclesInfo.totalVehicles"
}
}
},
{
$project: {
"_id": 0,
"culture": 1,
"results.createdOn": "$createdOn"
}
}
]).pretty()
Output:
{ "culture" : "de-de", "results" : { "createdOn" : 1 } }
{ "culture" : "it-it", "results" : { "createdOn" : 1 } }

Using document field as JS object field-name in aggregation pipeline

I have an JS object called tasksCountMap:
const tasksCountMap = {
'Freshman': 46,
'Senior': 10
}
and I need get count of task for each user type in my aggregation pipe, 'Freshman', 'Senior' it's document field called gradeLevel. I'm trying do it like this:
status: {
$let: {
vars: {
tasksCount: tasksCountMap['$gradeLevel'],
completedTasksCount: '$completedTasksCount[0].count'
},
in: {
$cond: {
if: { $or: [
{ $eq: ['$$tasksCount', '$$completedTasksCount'] },
{ $lte: ['$$tasksCount', '$$completedTasksCount'] },
]},
then: 'On track',
else: 'High priority'
}
}
}
}
Also '$completedTasksCount[0].count' doesn't work to...
Can someone show right way to do this?
All pipeline:
{
$match: {
type: 'student',
counselorUserName: username
},
$project: {
username: '$username',
email: '$email',
phone: '$phone',
fullName: '$fullName',
gradeLevel: {
$switch: {
branches: [{
case: {
$eq: ['$gradeLevel', '9']
},
then: 'Freshman'
},
{
case: {
$eq: ['$gradeLevel', '10']
},
then: 'Sophomore'
},
{
case: {
$eq: ['$gradeLevel', '11']
},
then: 'Junior'
},
{
case: {
$eq: ['$gradeLevel', '12']
},
then: 'Senior'
}
],
default: "Freshman"
}
}
},
$lookup: {
from: 'RoadmapTasksCompleted',
let: {
username: '$username',
gradeLevel: '$gradeLevel'
},
pipeline: [{
$match: {
monthToComplete: {
$in: prevMonthsNames
},
$expr: {
$and: [{
$eq: ['$username', '$$username']
},
{
$eq: ['$gradeLevel', '$$gradeLevel']
}
]
}
}
},
{
$count: 'count'
}
],
as: 'completedTasksCount'
},
$project: {
username: '$username',
email: '$email',
phone: '$phone',
fullName: '$fullName',
completedTask: { $arrayElemAt: ['$completedTasksCount', 0] },
status: {
$let: {
vars: {
tasksCount: tasksCountMap['$gradeLevel'],
completedTasksCount: '$completedTasksCount[0].count'
},
in: {
$cond: {
if: { $or: [
{ $eq: ['$$tasksCount', '$$completedTasksCount'] },
{ $lte: ['$$tasksCount', '$$completedTasksCount'] },
]},
then: '$$tasksCount',
else:'$$tasksCount'
}
}
}
}
}
$limit: 10,
$skip: 10,
}
You have to move the js map into the aggregation pipeline for you to be able to access the map.
I split $project stage into two and took the liberty to clean up the status calculation.
Something like
{"$project":{
"username":"$username",
"email":"$email",
"phone":"$phone",
"fullName":"$fullName",
"completedTask":{"$arrayElemAt":["$completedTasksCount",0]},
"tasksCountMap":[{"k":"Freshman","v":46},{"k":"Senior","v":10}]
}},
{"$addFields":{
"status":{
"$let":{
"vars":{
"tasksCount":{
"$arrayElemAt":[
"$tasksCountMap.v",
{"$indexOfArray":["$tasksCountMap.k","$gradeLevel"]}
]
},
"completedTasksCount":"$completedTask.count"
},
"in":{
"$cond":{
"if":{"$lte":["$$tasksCount","$$completedTasksCount"]},
"then":"$$tasksCount",
"else":"$$completedTasksCount"
}
}
}
}
}}