For Example, I have a collection of documents called Dialogs. Format:
Dialogs{
{
_id: ObjectId(),
members: [
"admin",
"all"
]
},
{
_id: ObjectId(),
members: [
"user_637b2ed34ce3130e8532c4b9",
"admin"
]
},
{
_id: ObjectId(),
members: [
"group_637c708927f9df62ca646623",
"admin"
]
},
{
_id: ObjectId(),
members: [
"admin",
"group_63a70e959fm566d28skkfi5b2",
"user_427b2ed34ce4h50e8532c92h"
]
},
}
I need to return sorted documents in this order: first documents containing only all, then documents containing all and some group, then just with a group, then group and users, then just users (each array has an admin string).
I tried to use aggregation, but nothing happened
One option is to add a field using $switch
:
db.collection.aggregate([
{$addFields: {memberTypes: {$map: {
input: "$members",
in: {$first: {$split: ["$$this", "_"]}}
}}}},
{$addFields: {
order: {$switch: {
branches: [
{
case: {$eq: [{$size: {$setUnion: ["$members", ["admin", "all"]]}}, 2]},
then: 1
},
{
case: {$in: ["all", "$members"]},
then: 2
},
{
case: {$and: [
{$in: ["group", "$memberTypes"]},
{$not: {$in: ["user", "$memberTypes"]}}
]},
then: 3
},
{
case: {$in: ["group", "$memberTypes"]}]},
then: 4
}
],
default: 5
}
}
}
},
{$sort: {order: 1}},
{$unset: ["memberTypes", "order"]}
])
See how it works on the playground example