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

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"
}
}
}
}
}}

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 loop through every distinct values and select tags using aggregate (facet)

I have collection like this:
{
"labels": [{
"description": "Dog"
}, {
"description": "Red"
}, {
"description": "XXX"
}]
}
{
"labels": [{
"description": "Cat"
}, {
"description": "XXX"
}, {
"description": "Yellow"
}]
}
{
"labels": [{
"description": "Dog"
}, {
"description": "Red"
}, {
"description": "Yellow"
}]
}
{
"labels": [{
"description": "Bird"
}, {
"description": "XXX"
}, {
"description": "XXX"
}]
}
I want to filter for example only "Red" and "Yellow" colors from ALL elements and output document like this:
// because "Dog" appears 2 times so total = 2
{
description: "Dog",
total: 2,
colors: [
{ "_id": "Red", total: 2 },
{ "_id": "Yellow", total: 1 }
]
}
{
description: "Cat",
total: 1,
colors: [
{ "_id": "Yellow", total: 1 }
]
}
{
description: "Bird",
total: 1,
colors: []
}
{
description: "Red",
total: 2,
colors: [
{ _id: "Yellow", total: 1 }
]
}
{
description: "XXX",
total: 4,
colors: [
{ _id: "Yellow", total: 1 }
]
}
I can do this by using collection.distinct('labels.description') and then iterating through every single element + make a separate collection.count({ 'labels.description': 'Dog' }) like this:
for (...)
db.collection.aggregate([
{
"$match": {
"labels.description": valueFromLoop // (e.g. Dog)
}
},
{ $unwind : "$labels" },
{
"$group": {
"_id": "$labels.description",
"count": { "$sum": 1 }
}
},
{
"$match": {
"$or": [
{ "_id": "Red" },
{ "_id": "Yellow" }
]
}
},
{
"$sort": {
"count": -1
}
}
])
I want to do this in a single aggregation or mapReduce so that I could easily output it to new collection using $out instead of using Bulk operations separately, however I don't know if it's possible.
Try this:
let filter = ["Red", "Yellow"];
db.testcollection.aggregate([
{
$addFields: { bkp: "$labels" }
},
{ $unwind: "$labels" },
{
$addFields: {
bkp: {
$filter: {
input: "$bkp",
as: "item",
cond: {
$and: [
{ $ne: ["$$item.description", "$labels.description"] },
{ $in: ["$$item.description", filter] }
]
}
}
}
}
},
{
$unwind: {
path: "$bkp",
preserveNullAndEmptyArrays: true
}
},
{
$group: {
_id: {
key1: "$labels.description",
key2: { $ifNull: ["$bkp.description", false] }
},
total: { $sum: 1 }
}
},
{
$group: {
_id: "$_id.key1",
description: { $first: "$_id.key1" },
total: {
$sum: {
$cond: {
if: { $first: [["$_id.key2"]] },
then: 1,
else: "$total"
}
}
},
colors: {
$push: {
$cond: {
if: { $first: [["$_id.key2"]] },
then: {
_id: "$_id.key2",
total: "$total"
},
else: "$$REMOVE"
}
}
}
}
},
{ $project: { _id: 0 } }
]);
For some reason with code from both answers it does not count all tags properly.
I'm posting what works:
db.collection.aggregate([
{
$project: {
labels: 1,
result: {
$filter: {
input: "$labels",
as: "label",
cond: {
$or: [
{ $eq: ["$$label.description", "Blue"] },
{ $eq: ["$$label.description", "Red"] },
{ $eq: ["$$label.description", "Black-and-white"] },
{ $eq: ["$$label.description", "Purple"] },
{ $eq: ["$$label.description", "Orange"] },
{ $eq: ["$$label.description", "Yellow"] },
{ $eq: ["$$label.description", "Green"] },
{ $eq: ["$$label.description", "Teal"] }
]
}
}
}
}
},
{
$unwind: "$labels"
},
{
"$group": {
_id: "$labels.description",
x: {
$push: "$result.description"
},
total: { "$sum": 1 }
}
},
{
$project: {
x: {
$reduce: {
input: '$x',
initialValue: [],
in: {$concatArrays: ['$$value', '$$this']}
}
},
total: 1
}
},
{
$project: {
x: 1,
y: { $setUnion: "$x" },
total: 1
}
},
{
$project: {
_id: 0,
description: "$_id",
"colors": {
$map: {
input: "$y",
as: "item",
in: {
_id: "$$item",
count: {
$size: {
$filter: {
input: "$x",
as: "itemx",
cond: {
$eq: ["$$item", "$$itemx"]
}
}
}
}
}
}
},
total: 1
}
},
{
$out: "backgrounds_meta"
}
])
db.test2.aggregate([
{
$project: {
labels:1,
colours: {
$filter: {
input: "$labels",
as: "label",
cond: {
$or: [
{$eq:["Yellow","$$label.description"]},
{$eq:["Red", "$$label.description"]}
]
}
}
}
}
},
{$unwind:"$labels"},
{$group:{
_id: "$labels.description",
total: {$sum:1},
colours: {$addToSet:"$colours.description"}
}},
{
$project:{
_id:0,
description:"$_id",
total:1,
colours: {
$reduce:{
input: "$colours",
initialValue: [],
in: {$concatArrays: ["$$value", "$$this"]}
}
}
}
},
{
$unwind: {
path:"$colours",preserveNullAndEmptyArrays: true
}
},
{
$group:{
_id:{
description:"$description",
total:"$total",
colour:"$colours"
},
count: {
$sum: {$cond:[{$ifNull:["$colours",false]},1,0]}
}
}
},
{
$group:{
_id:{
description:"$_id.description",
total:"$_id.total"
},
colours: {
$push: {
$cond: [{$gt:["$count",0]},
{
"_id":"$_id.colour",
total:"$count"
},
"$$REMOVE"
]
}
}
}
},
{
$project: {
_id:0,
description: "$_id.description",
total: "$_id.total",
colours: 1
}
}
]);
**Edit In your answer, you are missing the Yellows for Red and Dog because you are taking the first item from $result with $arrayElemAt: ["$result.description", 0].
If description is a colour, do you also want to include the counts for itself in colours?
Never mind, you've updated the answer

How to find prev/next document after sort in MongoDB

I want to find prev/next blog documents whose publish date is closest to the input document.
Below is the document structure.
Collection Examples (blog)
{
blogCode: "B0001",
publishDate: "2020-09-21"
},
{
blogCode: "B0002",
publishDate: "2020-09-22"
},
{
blogCode: "B0003",
publishDate: "2020-09-13"
},
{
blogCode: "B0004",
publishDate: "2020-09-24"
},
{
blogCode: "B0005",
publishDate: "2020-09-05"
}
If the input is blogCode = B0003
Expected output
{
blogCode: "B0005",
publishDate: "2020-09-05"
},
{
blogCode: "B0001",
publishDate: "2020-09-21"
}
How could I get the output result? In sql, it seems using ROW_NUMBER can solve my problem, however I can't find a solution to achieve the feature in MongoDB. The alternate solution may be reference to this answer (But, it seems inefficient). Maybe using mapReduce is another better solutions? I'm confused at the moment, please give me some help.
You can go like following.
We need to compare existing date with given date. So I used $facet to categorize both dates
The original data should be one Eg : B0003. So that I just get the first element of the origin[] array to compare with rest[] array
used $unwind to flat the rest[]
Substract to get the different between both dates
Again used $facet to find previous and next dates.
Then combined both to get your expected result
NOTE : The final array may have 0<elements<=2. The expected result given by you will not find out whether its a prev or next date if there is a one element. So my suggestion is add another field to say which date it is as the mongo playground shows
[{
$facet: {
origin: [{
$match: { blogCode: 'B0001' }
}],
rest: [{
$match: {
$expr: {
$ne: ['$blogCode','B0001']
}
}
}]
}
}, {
$project: {
origin: {
$arrayElemAt: ['$origin',0]
},
rest: 1
}
}, {
$unwind: {path: '$rest'}
}, {
$project: {
diff: {
$subtract: [{ $toDate: '$rest.publishDate' },{ $toDate: '$origin.publishDate'}]
},
rest: 1,
origin: 1
}
}, {
$facet: {
prev: [{
$sort: {diff: -1}
},
{
$match: {
diff: {$lt: 0 }
}
},
{
$limit: 1
},
{
$addFields:{"rest.type":"PREV"}
}
],
next: [{
$sort: { diff: 1 }
},
{
$match: {
diff: { $gt: 0 }
}
},
{
$limit: 1
},
{
$addFields:{"rest.type":"NEXT"}
}
]
}
}, {
$project: {
combined: {
$concatArrays: ["$prev", "$next"]
}
}
}, {
$unwind: {
path: "$combined"
}
}, {
$replaceRoot: {
newRoot: "$combined.rest"
}
}]
Working Mongo playground
Inspire for the solution of varman proposed. I also find another way to solve my problem by using includeArrayIndex.
[
{
$sort: {
"publishDate": 1
},
},
{
$group: {
_id: 1,
root: {
$push: "$$ROOT"
}
},
},
{
$unwind: {
path: "$root",
includeArrayIndex: "rownum"
}
},
{
$replaceRoot: {
newRoot: {
$mergeObjects: [
"$root",
{
rownum: "$rownum"
}
]
}
}
},
{
$facet: {
currRow: [
{
$match: {
blogCode: "B0004"
},
},
{
$project: {
rownum: 1
}
}
],
root: [
{
$match: {
blogCode: {
$exists: true
}
}
},
]
}
},
{
$project: {
currRow: {
$arrayElemAt: [
"$currRow",
0
]
},
root: 1
}
},
{
$project: {
rownum: {
prev: {
$add: [
"$currRow.rownum",
-1
]
},
next: {
$add: [
"$currRow.rownum",
1
]
}
},
root: 1
}
},
{
$unwind: "$root"
},
{
$facet: {
prev: [
{
$match: {
$expr: {
$eq: [
"$root.rownum",
"$rownum.prev"
]
}
}
},
{
$replaceRoot: {
newRoot: "$root"
}
}
],
next: [
{
$match: {
$expr: {
$eq: [
"$root.rownum",
"$rownum.next"
]
}
}
},
{
$replaceRoot: {
newRoot: "$root"
}
}
],
}
},
{
$project: {
prev: {
$arrayElemAt: [
"$prev",
0
]
},
next: {
$arrayElemAt: [
"$next",
0
]
},
}
},
]
Working Mongo playground

if condtion MongoDB aggregation

I need to display the currentLocation of which the process is completed,which are presented in four different collections. It's a chain process, in the order of labtest, inwards, goods, production. Each of them is different collections. I want the result in which, if labtest status is completed it goes to inwards, if inwards status also completed, then it goes and checks on goods. If goods status is In-Progress, it should return Inwards as currentLocation.
But, I am getting a response as Production....it seems like me if the condition is not working. Please help me to solve this issue
async function getGrnDetails(userParam) {
var user = User.findOne({ grnNo: userParam.grnNo })
var userss = User.aggregate([
{
$match:
{
grnNo: userParam.grnNo
}
}, {
$lookup: {
from: "goods",
let: { grnNo: "$grnNo" },
pipeline: [
{
$match: {
$expr:
{
$eq: ["$grnNo", '$$grnNo']
}
}
},
],
as: "Goods",
},
},
{
$lookup: {
from: "inwards",
let: { grnNo: "$grnNo" },
pipeline: [
{
$match: {
$expr:
{
$eq: ["$grnNo", '$$grnNo']
}
}
}
],
as: "Inwards",
}
},
{
$lookup: {
from: "productions",
let: { grnNo: "$grnNo" },
pipeline: [
{
$match: {
$expr:
{
$eq: ["$grnNo", '$$grnNo']
}
}
},
],
as: "Productions",
}
},
{
$unwind: {
"path": "$Productions"
}
},{
$unwind: {
"path": "$status"
}
},{
$unwind: {
"path": "$Goods"
}
},
{
$unwind: {
"path": "$Inwards"
}
},
{
$group: {
"_id": {
beforeHeadSettingArray: '$beforeHeadSettingArray',
beforeWashingArray: '$beforeWashingArray', id: '$id',
status: '$status', defaultAccountId: '$defaultAccountId',
beforeStenterArray: '$beforeStenterArray',
beforeCompactingArray: '$beforeCompactingArray',
afterCompactingArray: '$afterCompactingArray',
status: "$status",
Goods: '$Goods.processArray', Inwards: '$Inwards.fabricArray', Production: '$Productions.operationDisplay', currentLocation: {
$cond: {
if: {
$strcasecmp: ["$status", "Completed"]
}, then: {
$cond: {
if: {
$strcasecmp: ["$Inwards.status", "Completed"]
},
then: {
$cond: {
if: {
$strcasecmp: ["$Goods.status", "Completed"]
},
then:
{
$cond: {
if: {
$strcasecmp: ["$Productions.status", "Completed"]
},
then: "Productions",
else: "Goods"
}
},
else: "Inwards"
}
},
else: "LabTest"
}
},
else: "Yet To be Started"
}
}
},
"ProgressArray": {
$addToSet: {
"Inwards": "$Inwards.status",
"Goods": "$Goods.status",
"Productions": "$Productions.status",
"LabTest": "$status"
},
}
}
} ,{ $sort: { _id: 1 } },
{ $limit: 1 }
]);
return await userss
}
The Problem is I used strcasecmp, when I changed to eq it worked perfectly
currentLocation: {
$cond: {
if: {
$eq: ["$status", "Completed"]
}, then: {
$cond: {
if: {
$eq: ["$Inwards.status", "Completed"]
},
then: {
$cond: {
if: {
$eq: ["$Goods.status", "Completed"]
},
then:
{
$cond: {
if: {
$eq: ["$Productions.status", "Completed"]
},
then: "Finished",
else: "Productions"
}
},
else: "Goods"
}
},
else: "Inwards"
}
},
else: "LabTest"
}
}
,

Returning a document with two fields from the same array in MongoDB

Given documents such as
{
_id: 'abcd',
userId: '12345',
activities: [
{ status: 'login', timestamp: '10000001' },
{ status: 'logout', timestamp: '10000002' },
{ status: 'login', timestamp: '10000003' },
{ status: 'logout', timestamp: '10000004' },
]
}
I am trying to create a pipeline such as all users that have their latest login/logout activities recorded between two timestamps will be returned. For example, if the two timestamp values are between 10000002 and 10000003, the expected document should be
{
_id: 'abcd',
userId: '12345',
login: '10000003',
logout: '10000002'
}
Of if the two timestamp values are between -1 and 10000001, the expected document should be :
{
_id: 'abcd',
userId: '12345',
login: '10000001',
logout: null
}
Etc.
I know it has to do with aggregations, and I need to $unwind, etc., but I'm not sure about the rest, namely evaluating two fields from the same document array
You can try below aggregation:
db.col.aggregate([
{
$unwind: "$activities"
},
{
$match: {
$and: [
{ "activities.timestamp": { $gte: "10000001" } },
{ "activities.timestamp": { $lte: "10000002" } }
]
}
},
{
$sort: {
"activities.timestamp": -1
}
},
{
$group: {
_id: "$_id",
userId: { $first: "$userId" },
activities: { $push: "$activities" }
}
},
{
$addFields: {
login: { $arrayElemAt: [ { $filter: { input: "$activities", as: "a", cond: { $eq: [ "$$a.status", "login" ] } } } , 0 ] },
logout: { $arrayElemAt: [ { $filter: { input: "$activities", as: "a", cond: { $eq: [ "$$a.status", "logout" ] } } } , 0 ] }
}
},
{
$project: {
_id: 1,
userId: 1,
login: { $ifNull: [ "$login.timestamp", null ] },
logout: { $ifNull: [ "$logout.timestamp", null ] }
}
}
])
We need to use $unwind + $sort + $group to make sure that our activities will be sorted by timestamp. After $unwind you can use $match to apply filtering condition. Then you can use $filter with $arrayElemAt to get first (latest) value of filtered array. In the last $project you can explicitly use $ifNull (otherwise JSON key will be skipped if there's no value)
You can use below aggregation
Instead of $unwind use $lte and $gte with the $fitler aggregation.
db.collection.aggregate([
{ "$project": {
"userId": 1,
"login": {
"$max": {
"$filter": {
"input": "$activities",
"cond": {
"$and": [
{ "$gte": ["$$this.timestamp", "10000001"] },
{ "$lte": ["$$this.timestamp", "10000004"] },
{ "$lte": ["$$this.status", "login"] }
]
}
}
}
},
"logout": {
"$max": {
"$filter": {
"input": "$activities",
"cond": {
"$and": [
{ "$gte": ["$$this.timestamp", "10000001"] },
{ "$lte": ["$$this.timestamp", "10000004"] },
{ "$lte": ["$$this.status", "logout"] }
]
}
}
}
}
}}
])