【问题标题】:How To Sort mongodb query results based on subdocuments如何根据子文档对mongodb查询结果进行排序
【发布时间】:2013-09-30 23:38:59
【问题描述】:

我在分数集合(学生)数据库中有 2 个文档,如下面的 mongodb 数据库。

{ 
    id: 2, 
    type: 'newname', 
    subs: [
        { time: 20, val: 'b' },
        { time: 12, val: 'a' },
        { time: 30, val: 'c' }
    ] }, { 
    id: 1, 
    type: 'strs', 
    subs: [
        { time: 50, val: 'be' },
        { time: 1, val: 'ab' },
        { time: 20, val: 'cs' }
    ] }

如何构造查询以获得以下结果

{ 
    id: 1, 
    type: 'strs', 
    subs: [
        { time: 1, val: 'ab' },
        { time: 20, val: 'cs' },
        { time: 50, val: 'be' }
    ]
},
{ 
    id: 2, 
    type: 'newname', 
    subs: [
        { time: 12, val: 'a' },
        { time: 20, val: 'b' },
        { time: 30, val: 'c' }
    ]
}

ie:基于时间查找文档的查询,并且必须根据 2 个条件对结果进行排序

  1. 作者 id ASC
  2. 按子文档时间 ASC

【问题讨论】:

  • 我也需要这样做,你能分享你的解决方案吗?

标签: mongodb


【解决方案1】:

顺序使用时可以$unwind > $sort > $group 专用于数组,

db.collection.aggregate([
  { $unwind: "$subs" },
  • $sort subs.time 升序(1)
  { $sort: { "subs.time": 1 } },
  • $group by id,并使用$push 重新构造subs 数组,对象和其他字段仍然使用$first
  {
    $group: {
      _id: "$id",
      id: { $first: "$id" },
      type: { $first: "$type" },
      subs: { $push: "$subs" }
    }
  },
  { $project: { _id: 0 } },
  • $sort id 按升序排列
  { $sort: { id: 1 } }
])

Playground

【讨论】:

    【解决方案2】:

    奇怪的是,MongoDB 没有提供任何通过查询来对子文档进行排序的方法。看来您必须更新子文档的自然排序顺序,如下所示:

    如果这些是您收藏中仅有的 2 个文档,请在下面写下查询:

    db.test.update( {}, {$push : {"subs" :{$each  : [] , $sort : {time : -1}}}})
    

    然后运行查询以对 ID 本身进行排序:

    db.test.find().sort({'id':1}).pretty()
    

    你会得到下面的输出。

    {                                                             
    
            "id" : 1,                                             
            "type" : "strs",                                      
            "subs" : [                                            
                    {                                             
                            "time" : 50,                          
                            "val" : "be"                          
                    },                                            
                    {                                             
                            "time" : 20,                          
                            "val" : "cs"                          
                    },                                            
                    {                                             
                            "time" : 1,                           
                            "val" : "ab"                          
                    }                                             
            ]                                                     
    }                                                             
    {                                                             
    
            "id" : 2,                                             
            "type" : "newname",                                   
            "subs" : [                                            
                    {                                             
                            "time" : 30,                          
                            "val" : "c"                           
                    },                                            
                    {                                             
                            "time" : 20,                          
                            "val" : "b"                           
                    },                                            
                    {                                             
                            "time" : 12,                          
                            "val" : "a"                           
                    }                                             
            ]                                                     
    }     
    

    希望它能解决你的情况。以下是参考:

    http://docs.mongodb.org/manual/reference/operator/update/sort/#sort-array-of-documents-by-a-field-in-the-documents

    【讨论】:

      【解决方案3】:

      您可以使用cursor.sort() 同时对多个字段(基本上是一个组合)进行排序,但我认为它在同时对文档和子文档字段进行排序时不起作用。 如果您要对顶部文档的两个不同字段或子文档的两个不同字段进行排序,那么我猜会很好。

      因此,您可以使用aggregation 框架获得类似的输出。您所要做的基本上就是分解subs 字段的数组,然后分解sort 它们。

      你可以这样做:

      db.col.aggregate({$unwind:'subs'}, {$sort:{id:1,'subs.time':1}});
      

      使用上面的代码,你应该得到类似这样的输出:

       { 
          id: 1, 
          type: 'strs', 
          subs: 
              { time: 1, val: 'ab' }
      },{ 
          id: 1, 
          type: 'strs', 
          subs: 
              { time: 20, val: 'cs' }
      },{ 
          id: 1, 
          type: 'strs', 
          subs: 
              { time: 50, val: 'be' }
      },{ 
          id: 2, 
          type: 'newname', 
          subs: 
              { time: 12, val: 'a' }
      },{ 
          id: 2, 
          type: 'newname', 
          subs: 
              { time: 20, val: 'b' }
      },{ 
          id: 2, 
          type: 'newname', 
          subs: 
              { time: 30, val: 'c' }
      }
      

      【讨论】:

      • 预期的解决方案是 { id: 1, type: 'strs', subs: [ { time: 1, val: 'ab' }, { time: 20, val: 'cs' }, { time: 50, val: 'be' } ] }, { id: 2, type: 'newname', subs: [ { time: 12, val: 'a' }, { time: 20, val: 'b' }, { 时间: 30, val: 'c' } ] }
      • 正确,我已经有一段时间没有看到了,但是您可以将其分组为我编写的聚合的最后一步,并使用 $addToSet 来获得所需的输出。如果你愿意,我可以写查询...
      • @tzik 请编写完整的查询以获得预期的解决方案。我也需要这样做
      • @tzik 你可以回答这个问题:[stackoverflow.com/questions/63378828/…
      【解决方案4】:

      你可以使用cursor.sort(sort)

      例如:

      db.collection.find().sort( { 'id': 1 } )
      

      使用 id 升序对结果进行排序。

      更多详情请参考以下链接。 http://docs.mongodb.org/manual/reference/method/cursor.sort/

      【讨论】:

      • 如何对包含列表项的子文档进行排序,我需要根据列表中的内键时间对列表进行排序。这就是我最需要的
      • 我认为排序子文档是不可能的stackoverflow.com/questions/3848814/…
      猜你喜欢
      • 2014-05-10
      • 1970-01-01
      • 2016-07-25
      • 2017-05-09
      • 1970-01-01
      • 1970-01-01
      • 2021-10-22
      • 2016-03-17
      相关资源
      最近更新 更多