鉴于以下收集:
[
{
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}
]
}
]
如何按“分数”对这些项目进行排序?我可以按metadata.v字段排序,但我不确定如何只考虑匹配“k”的子文档的“v”值:“得分”
预期输出为:
[
{
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}
]
}
]
答案 0 :(得分:2)
替代解决方案可能如下所示,如果您可以使用额外的scoredata
属性,则最终投影阶段是可选的。
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
}
}
])
输出看起来像这样
/* 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
}
]
}
答案 1 :(得分:1)
您可以使用aggregate
执行此操作,方法是在展开元数据以进行过滤和排序之前,将每个文档的副本与其metadata
一起投影:
db.test.aggregate([
// Project a copy of each document along with its metadata
{$project: {doc: '$$ROOT', metadata: '$metadata'}},
// Duplicate the docs, one per metadata element
{$unwind: '$metadata'},
// Filter to just the score metadata for sorting
{$match: {'metadata.k': 'score'}},
// Sort on the score values
{$sort: {'metadata.v': 1}},
// Project just the original docs in their sorted order
{$project: {_id: 0, doc: '$doc'}}
])
输出:
{
"doc" : {
"_id" : ObjectId("57962f891be8975795eee18a"),
"name" : "User2",
"metadata" : [
{
"k" : "score",
"v" : 1.0
},
{
"k" : "other",
"v" : 1.0
}
]
}
}
{
"doc" : {
"_id" : ObjectId("57962f891be8975795eee18b"),
"name" : "User3",
"metadata" : [
{
"k" : "score",
"v" : 2.0
},
{
"k" : "other",
"v" : 0.0
}
]
}
}
{
"doc" : {
"_id" : ObjectId("57962f891be8975795eee189"),
"name" : "User1",
"metadata" : [
{
"k" : "score",
"v" : 5.0
},
{
"k" : "other",
"v" : 10.0
}
]
}
}
您可以更改最终$project
以重新整理文档,以便在需要时将doc
字段提升回顶级。
答案 2 :(得分:0)
使用$elemMatch
中的aggregate
符合您的条件,并按metadata.v
排序查看以下查询
db.collection.aggregate({"$match":{"metadata":{"$elemMatch":{"k":"score"}}}},
{"$sort":{"metadata.v":1}}).pretty()