Reputation:
I have documents with structure similar to this:
{
users_ids: [
"122djdj-sdsddsl-3232323",
"2332333-443rdds-sdadads"
],
users_roles: {
"122djdj-sdsddsl-3232323": "admin",
"2332333-443rdds-sdadads": "moderator"
},
users_names: {
"122djdj-sdsddsl-3232323": "John Smith",
"2332333-443rdds-sdadads": "Paul Newman"
}
}
users_ids is array with users, then are objects with different properties. Now, I would like to make query and get document with additional fields like:
adminId: 122djdj-sdsddsl-3232323
adminName: John Smith
All these fields will be non-dynamic, i.e. will be defined in query. I need them to sort values using for example admin name (so I first must know, who is admin, then add field with admin name). My question: how can I use field from document in other expressions? I though about first add fields:
{
$addFields: {
userA: { $arrayElemAt: ["$users_ids", 0] },
userB: { $arrayElemAt: ["$users_ids", 1] },
}
}
And then use $userA and $userB in other conditions - but any method doesn't work, also tried $objectToArray without success:
{
$addFields: {
roles: { $objectToArray: "$users_roles" }
}
},
{
$addFields: {
// Doesnt work
adminName: {
$cond: {
if: {
$eq: ["$roles[0].v", 'admin']
},
then: "$roles[0].k",
else: "$roles[1].k"
}
}
}
}
Upvotes: 1
Views: 220
Reputation: 49945
You have to start with $objectToArray
since your key names are dynamic (you can rethink that design). Then you need to run a combination of $arrayElemAt
and $filter
to get first matching element:
db.collection.aggregate([
{
$addFields: {
user_roles_arr: { $objectToArray: "$users_roles" },
user_names_arr: { $objectToArray: "$users_names" },
}
},
{
$addFields: {
admin: {
$arrayElemAt: [
{ $filter: { input: "$user_roles_arr", cond: { $eq: [ "$$this.v", "admin" ] } } }, 0
]
}
}
},
{
$addFields: {
adminId: "$admin.k",
adminName: {
$let: {
vars: { adm: { $arrayElemAt: [ { $filter: { input: "$user_names_arr", cond: { $eq: [ "$admin.k", "$$this.k" ] } } }, 0 ] } },
in: "$$adm.v"
}
}
}
},
{
$project: {
user_roles_arr: 0,
user_names_arr: 0,
admin: 0
}
}
])
Upvotes: 0