Given the following collection:
[
{
name: User1
metadata: [
{k:"score", v: 5},
{k:"other", v: 10}
]
},
{
name: User2
metadata: [
{k:"score", v: 1},
{k:"other", v: 1}
]
},
{
name: User3
metadata: [
{k:"score", v: 2},
{k:"other", v: 0}
]
}
]
How can you sort these items by their "score"? I can sort by the metadata.v field, but I am not sure how to only consider the "v" values for subdocuments that match "k":"score"
The expected output would be:
[
{
name: User2
metadata: [
{k:"score", v: 1},
{k:"other", v: 1}
]
},
{
name: User3
metadata: [
{k:"score", v: 2},
{k:"other", v: 0}
]
},
{
name: User1
metadata: [
{k:"score", v: 5},
{k:"other", v: 10}
]
}
]
An alternative solution could look like this, whereby the final projection stage is optional if you can live with an additional scoredata
property.
db.yourCollection.aggregate([
{
$project: {
name: 1,
metadata: 1,
scoredata: {
$filter: {
input: '$metadata',
as: 'metadoc',
cond: {
$eq: [ '$$metadoc.k', 'score' ]
}
}
}
}
},
{
$sort: {
scoredata: 1
}
},
{
$project: {
name: 1,
metadata: 1
}
}
])
Output looks like this
/* 1 */
{
"_id" : ObjectId("5796387b3360e0a2e9dd9fc3"),
"name" : "User2",
"metadata" : [
{
"k" : "score",
"v" : 1
},
{
"k" : "other",
"v" : 1
}
]
}
/* 2 */
{
"_id" : ObjectId("5796387b3360e0a2e9dd9fc4"),
"name" : "User3",
"metadata" : [
{
"k" : "score",
"v" : 2
},
{
"k" : "other",
"v" : 0
}
]
}
/* 3 */
{
"_id" : ObjectId("5796387b3360e0a2e9dd9fc2"),
"name" : "User1",
"metadata" : [
{
"k" : "score",
"v" : 5
},
{
"k" : "other",
"v" : 10
}
]
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With