Hey @boomography,
Here is my attempt in Python. Just to try different things, I generated a bunch of docs randomly and then I wrote the pipeline in Compass and copy/pasted it in Python.
Let me l know what you think:
import random
from pprint import pprint
from faker import Faker
from pymongo import MongoClient
fake = Faker()
def rand_person():
return random.choice(["Alice", "Bob", "Max", "Boom", "Nic", "John", "Joe"])
def rand_state():
return random.choice(["pending", "completed", "rejected", "queued"])
def rand_tickets():
return [{
'assigned': rand_person(),
'responsible': rand_person(),
'name': fake.text(max_nb_chars=20),
'status': rand_state()
} for _ in range(100)]
if __name__ == '__main__':
client = MongoClient()
db = client.get_database('test')
tickets = db.get_collection('tickets')
tickets.drop()
tickets.create_index("assigned")
tickets.create_index("responsible")
tickets.insert_many(rand_tickets())
user = "Boom"
pipeline = [
{
'$match': {
'$or': [
{
'assigned': user
}, {
'responsible': user
}
]
}
}, {
'$group': {
'_id': None,
'docs': {
'$push': '$$ROOT'
}
}
}, {
'$project': {
'assigned': {
'pending': {'$filter': {'input': '$docs', 'as': 'item', 'cond': {'$and': [{'$eq': ['$$item.assigned', user]}, {'$eq': ['$$item.status', 'pending']}]}}},
'completed': {'$filter': {'input': '$docs', 'as': 'item', 'cond': {'$and': [{'$eq': ['$$item.assigned', user]}, {'$eq': ['$$item.status', 'completed']}]}}},
'rejected': {'$filter': {'input': '$docs', 'as': 'item', 'cond': {'$and': [{'$eq': ['$$item.assigned', user]}, {'$eq': ['$$item.status', 'rejected']}]}}},
'queued': {'$filter': {'input': '$docs', 'as': 'item', 'cond': {'$and': [{'$eq': ['$$item.assigned', user]}, {'$eq': ['$$item.status', 'queued']}]}}}
},
'responsible': {
'pending': {'$filter': {'input': '$docs', 'as': 'item', 'cond': {'$and': [{'$eq': ['$$item.responsible', user]}, {'$eq': ['$$item.status', 'pending']}]}}},
'completed': {'$filter': {'input': '$docs', 'as': 'item', 'cond': {'$and': [{'$eq': ['$$item.responsible', user]}, {'$eq': ['$$item.status', 'completed']}]}}},
'rejected': {'$filter': {'input': '$docs', 'as': 'item', 'cond': {'$and': [{'$eq': ['$$item.responsible', user]}, {'$eq': ['$$item.status', 'rejected']}]}}},
'queued': {'$filter': {'input': '$docs', 'as': 'item', 'cond': {'$and': [{'$eq': ['$$item.responsible', user]}, {'$eq': ['$$item.status', 'queued']}]}}}
}
}
}
]
for res in tickets.aggregate(pipeline):
pprint(res)
Final result looks like this:
{'_id': None,
'assigned': {'completed': [{'_id': ObjectId('62ace5bae1e2057c790a5d7b'),
'assigned': 'Boom',
'name': 'Lose someone.',
'responsible': 'Bob',
'status': 'completed'},
{'_id': ObjectId('62ace5bae1e2057c790a5d96'),
'assigned': 'Boom',
'name': 'Tend plant reveal.',
'responsible': 'Joe',
'status': 'completed'},
{'_id': ObjectId('62ace5bae1e2057c790a5dd0'),
'assigned': 'Boom',
'name': 'State state around.',
'responsible': 'Nic',
'status': 'completed'}],
'pending': [{'_id': ObjectId('62ace5bae1e2057c790a5d8a'),
'assigned': 'Boom',
'name': 'Ask well prove.',
'responsible': 'John',
'status': 'pending'},
{'_id': ObjectId('62ace5bae1e2057c790a5d9c'),
'assigned': 'Boom',
'name': 'Contain development.',
'responsible': 'John',
'status': 'pending'},
{'_id': ObjectId('62ace5bae1e2057c790a5d9d'),
'assigned': 'Boom',
'name': 'Mouth strategy.',
'responsible': 'Alice',
'status': 'pending'},
{'_id': ObjectId('62ace5bae1e2057c790a5da6'),
'assigned': 'Boom',
'name': 'Clear fire feeling.',
'responsible': 'Boom',
'status': 'pending'},
{'_id': ObjectId('62ace5bae1e2057c790a5daf'),
'assigned': 'Boom',
'name': 'Fall bring feel.',
'responsible': 'Nic',
'status': 'pending'},
{'_id': ObjectId('62ace5bae1e2057c790a5db3'),
'assigned': 'Boom',
'name': 'Manage but himself.',
'responsible': 'Max',
'status': 'pending'},
{'_id': ObjectId('62ace5bae1e2057c790a5dc3'),
'assigned': 'Boom',
'name': 'So suffer accept.',
'responsible': 'Nic',
'status': 'pending'},
{'_id': ObjectId('62ace5bae1e2057c790a5dd5'),
'assigned': 'Boom',
'name': 'Ever foot different.',
'responsible': 'Bob',
'status': 'pending'}],
'queued': [{'_id': ObjectId('62ace5bae1e2057c790a5d9f'),
'assigned': 'Boom',
'name': 'Reason after.',
'responsible': 'Alice',
'status': 'queued'}],
'rejected': [{'_id': ObjectId('62ace5bae1e2057c790a5db7'),
'assigned': 'Boom',
'name': 'Middle understand.',
'responsible': 'John',
'status': 'rejected'},
{'_id': ObjectId('62ace5bae1e2057c790a5dc5'),
'assigned': 'Boom',
'name': 'South camera get.',
'responsible': 'Joe',
'status': 'rejected'}]},
'responsible': {'completed': [{'_id': ObjectId('62ace5bae1e2057c790a5d90'),
'assigned': 'Joe',
'name': 'Letter tax agent.',
'responsible': 'Boom',
'status': 'completed'},
{'_id': ObjectId('62ace5bae1e2057c790a5db6'),
'assigned': 'Bob',
'name': 'West hand before.',
'responsible': 'Boom',
'status': 'completed'},
{'_id': ObjectId('62ace5bae1e2057c790a5dc9'),
'assigned': 'Bob',
'name': 'Feeling minute card.',
'responsible': 'Boom',
'status': 'completed'}],
'pending': [{'_id': ObjectId('62ace5bae1e2057c790a5da6'),
'assigned': 'Boom',
'name': 'Clear fire feeling.',
'responsible': 'Boom',
'status': 'pending'},
{'_id': ObjectId('62ace5bae1e2057c790a5da3'),
'assigned': 'John',
'name': 'Democratic it.',
'responsible': 'Boom',
'status': 'pending'},
{'_id': ObjectId('62ace5bae1e2057c790a5daa'),
'assigned': 'John',
'name': 'Account natural.',
'responsible': 'Boom',
'status': 'pending'}],
'queued': [{'_id': ObjectId('62ace5bae1e2057c790a5d7a'),
'assigned': 'John',
'name': 'Understand not.',
'responsible': 'Boom',
'status': 'queued'},
{'_id': ObjectId('62ace5bae1e2057c790a5d94'),
'assigned': 'Alice',
'name': 'When toward college.',
'responsible': 'Boom',
'status': 'queued'}],
'rejected': [{'_id': ObjectId('62ace5bae1e2057c790a5d83'),
'assigned': 'Joe',
'name': 'How cup simple back.',
'responsible': 'Boom',
'status': 'rejected'},
{'_id': ObjectId('62ace5bae1e2057c790a5d9a'),
'assigned': 'Joe',
'name': 'They task member.',
'responsible': 'Boom',
'status': 'rejected'},
{'_id': ObjectId('62ace5bae1e2057c790a5db1'),
'assigned': 'Alice',
'name': 'Operation any.',
'responsible': 'Boom',
'status': 'rejected'},
{'_id': ObjectId('62ace5bae1e2057c790a5dcc'),
'assigned': 'Joe',
'name': 'Interview itself.',
'responsible': 'Boom',
'status': 'rejected'},
{'_id': ObjectId('62ace5bae1e2057c790a5dcf'),
'assigned': 'Bob',
'name': 'Very teach beyond.',
'responsible': 'Boom',
'status': 'rejected'}]}}
Maybe there is a more sexy & optimized approach but I think it works. With $slice and $sortArray (v5.2+) you could refine even more the array if you like. You can also sort the array before the $group
by Null.
It’s also trivial to add a filter in the $filter conditions if you want the createdAt
field > X for instance.
Cheers,
Maxime.