MongoDB按嵌套数组排序

MongoDB按嵌套数组排序,mongodb,sorting,mapreduce,aggregation-framework,Mongodb,Sorting,Mapreduce,Aggregation Framework,我现在使用mongodb来获得我想要的东西 { “_id”:ObjectId(“533b66f3e4b038c01f6a427f”), “ccNameCount”:[{ “ccName”:“ATCC”, “纸张计数”:4660, “应变计数”:9339, “版本”:1 }, { “ccName”:“密件抄送”, “文件计数”:24, “应变计数”:41 }, { “ccName”:“BCCM/DCG”, “文件计数”:3, “应变计数”:7 }] } 示例文档就是这样。现在,我想查询ccNam

我现在使用mongodb来获得我想要的东西

{
“_id”:ObjectId(“533b66f3e4b038c01f6a427f”),
“ccNameCount”:[{
“ccName”:“ATCC”,
“纸张计数”:4660,
“应变计数”:9339,
“版本”:1
}, {
“ccName”:“密件抄送”,
“文件计数”:24,
“应变计数”:41
}, {
“ccName”:“BCCM/DCG”,
“文件计数”:3,
“应变计数”:7
}]
}
示例文档就是这样。现在,我想查询ccNameCount.ccName=ATCC的文档,并按paperCount对结果进行排序。但当然,由于ccNameCount是一个数组,只按键ccNameCount排序并不能得到我想要的内容。因此,我的问题是,我能做什么?使用MapReduce?

您最好的选择是:

db.collection.aggregate([
//匹配包含您的条件的“文档”
//减小工作尺寸
{“$match”:{
“ccNameCount.ccName”:“ATCC”
}},
//保留原始文档,您可能并不真正关心这一点
{“$project”:{
“_id”:{
“\u id”:“$\u id”,
“ccNameCount”:“$ccNameCount”
},
“ccNameCount”:1
}},
//展开数组以取消规格化
{“$unwind”:“$ccNameCount”},
//现在只需将这些元素(现在是文档)匹配为您的条件
{“$match”:{
“ccNameCount.ccName”:“ATCC”
}},
//按现在选择的“paperCount”对结果进行排序
{“$sort”:{“ccNameCount.paperCount”:-1},
//如果需要,请将文档恢复正常
{“$project”:{
“\u id”:“$\u id.\u id”,
“ccNameCount”:“$\u id.ccNameCount”
}}
])
因此,在实际“选择”匹配的数组元素之后,结果可以按此位置的字段排序。如果您想在结果中恢复数组的原始状态,则
$project
阶段是可选的,否则阶段仅选择匹配的条目并正确排序您最好的选择是:

db.collection.aggregate([
//匹配包含您的条件的“文档”
//减小工作尺寸
{“$match”:{
“ccNameCount.ccName”:“ATCC”
}},
//保留原始文档,您可能并不真正关心这一点
{“$project”:{
“_id”:{
“\u id”:“$\u id”,
“ccNameCount”:“$ccNameCount”
},
“ccNameCount”:1
}},
//展开数组以取消规格化
{“$unwind”:“$ccNameCount”},
//现在只需将这些元素(现在是文档)匹配为您的条件
{“$match”:{
“ccNameCount.ccName”:“ATCC”
}},
//按现在选择的“paperCount”对结果进行排序
{“$sort”:{“ccNameCount.paperCount”:-1},
//如果需要,请将文档恢复正常
{“$project”:{
“\u id”:“$\u id.\u id”,
“ccNameCount”:“$\u id.ccNameCount”
}}
])

因此,在实际“选择”匹配的数组元素之后,结果可以按此位置的字段排序。如果您想在结果中重新获得数组的原始状态,则
$project
阶段是可选的,否则阶段仅选择匹配条目并正确排序

您好,谢谢您的回答,我现在明白了。但我有一个非常小的问题。您有两个$match操作,在$unwind之前和$unwind之后,我知道它们的不同功能,但是我应该在java代码中使用什么使$match发生两次呢?@Vico_Wu,正如stages上的评论所说,它们在做两件完全不同的事情。第一个
$match
过滤文档。筛选文档和筛选数组项非常不同。展开后的第二条语句实际上只选择匹配的元素。因此,第一个
$match
的目的是仅选择具有该匹配元素的文档。如果所有文档都有该字段,则第一个匹配项是多余的。如果没有,首先删除完全不匹配的文档是您最好的性能提升。您好,谢谢您的回复,我现在明白了。但我有一个非常小的问题。您有两个$match操作,$unwind之前和$unwind之后,我知道它们的不同功能,但是,我应该在java代码中使用什么使$match出现两次呢?@Vico_Wu在stages上的评论中说,它们在做两件完全不同的事情。第一个
$match
过滤文档。筛选文档和筛选数组项非常不同。展开后的第二条语句实际上只选择匹配的元素。因此,第一个
$match
的目的是仅选择具有该匹配元素的文档。如果所有文档都有该字段,则第一个匹配项是多余的。但是,如果不匹配,则最好先删除根本不匹配的文档。