【问题标题】:MongoDB sort by nested arrayMongoDB按嵌套数组排序
【发布时间】:2014-04-30 01:52:42
【问题描述】:

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

{
  "_id" : ObjectId("533b66f3e4b038c01f6a427f"),
  "ccNameCount" : [{
      "ccName" : "ATCC",
      "paperCount" : 4660,
      "strainCount" : 9339,
      "version" : 1
    }, {
      "ccName" : "BCC",
      "paperCount" : 24,
      "strainCount" : 41
    }, {
      "ccName" : "BCCM/DCG",
      "paperCount" : 3,
      "strainCount" : 7
    }]
}

示例文档就是这样。现在,我想查询ccNameCount.ccName = ATCC的文档,并按paperCount对结果进行排序。但是当然,由于ccNameCount是一个数组,仅按ccNameCount键排序不会给出我想要什么。所以,我的问题是,我能做什么?使用 MapReduce?

【问题讨论】:

    标签: mongodb sorting mapreduce aggregation-framework


    【解决方案1】:

    您最好的选择是aggregation framework

    db.collection.aggregate([
    
        // Match the "documents" that contain your condition
        // reduces the working size
        { "$match": {
            "ccNameCount.ccName": "ATCC"
        }},
    
        // Keep the original document, you might not really care about this
        { "$project": {
            "_id": {
                "_id": "$_id",
                "ccNameCount": "$ccNameCount"
            },
            "ccNameCount": 1
       }},
    
        // Unwind the array to de-normalize
        { "$unwind": "$ccNameCount" },
    
        // Now just match those elements (now documents) as your condition
        { "$match": {
            "ccNameCount.ccName": "ATCC"
        }},
    
        // Sort the results on the now selected "paperCount"
        { "$sort": { "ccNameCount.paperCount": -1 } },
    
        // Put the documents back to normal if you want
        { "$project": {
            "_id": "$_id._id",
            "ccNameCount": "$_id.ccNameCount"
        }}
    
    ])
    

    因此,在此实际“选择”匹配的数组元素之后,结果可以按此位置的字段进行排序。 $project 阶段是可选的,如果您想在结果中恢复数组的原始状态,否则这些阶段只会选择匹配的条目并正确排序

    【讨论】:

    • 嗨,谢谢你的回复,我现在明白了。但是我有一个很小的问题。你有两个 $match 操作,在 $unwind 之前和 $unwind 之后,我知道它们的不同功能,但是我应该在我的 java 代码中做什么才能使 $match 发生两次?
    • @Vico_Wu 正如舞台上的 cmets 所说,他们正在做两件完全不同的事情。第一个$match 过滤文档。过滤文档和过滤数组项是非常不同的。第二个语句after unwind 实际上只选择匹配的元素。因此,first $match 的目的是 选择具有该匹配元素的文档。如果您的所有文档都有该字段,则第一个匹配项是多余的。但如果不是,最好先删除根本不匹配的文档。
    猜你喜欢
    • 1970-01-01
    • 2021-08-07
    • 1970-01-01
    • 2020-02-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-07
    • 1970-01-01
    相关资源
    最近更新 更多