如何基于子文档对MongoDB查询结果进行排序

5

我有两个文档在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' }
    ]
}

查询基于时间的文档并按照两个标准排序:

  1. id 升序排列
  2. 按子文档中的 时间 升序排列

我需要做同样的事情,你能分享一下你的解决方案吗? - s4suryapal
4个回答

6
您可以使用cursor.sort()对多个字段(基本上是组合)进行排序,但我认为当同时对文档和子文档字段进行排序时,它不起作用。 如果您要对顶级文档的两个不同字段或子文档的两个不同字段进行排序,则应该没问题。
因此,您可以使用聚合框架获得类似的输出。您所要做的就是基本上分解subs字段的数组,然后排序它们。
您可以像这样做:
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' }, { time: 30, val: 'c' } ] } - Arun K
没错,我已经有一段时间没有看到过那个了,但是你可以在我写的聚合的最后一步进行分组,并使用$addToSet来获得所需的输出。如果你想的话,我可以写出查询... - tzik
@tzik 请编写完整的查询以获得预期的解决方案。我需要做同样的事情。 - s4suryapal
@tzik,你可以回答这个问题:[https://stackoverflow.com/questions/63378828/mongoose-query-to-sort-main-document-subdocument-by-particular-field] - s4suryapal

3

奇怪的是,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

0

当使用顺序 $unwind > $sort > $group 时,可以对数组进行特殊处理。

db.collection.aggregate([
  { $unwind: "$subs" },
  • $sort 按升序排列 subs.time (1)
  { $sort: { "subs.time": 1 } },
  • 通过id$group,并使用$push对象重新构建subs数组,同时保留其他字段使用$first
  {
    $group: {
      _id: "$id",
      id: { $first: "$id" },
      type: { $first: "$type" },
      subs: { $push: "$subs" }
    }
  },
  { $project: { _id: 0 } },
  • 按升序id排序$sort
  { $sort: { id: 1 } }
])

游乐场


-2

我该如何对包含列表项的子文档进行排序,然后根据列表中的内部键时间对列表进行排序。这是我最需要的。 - Naveen Subramani
我认为在MongoDB中对子文档进行排序是不可能的。https://dev59.com/gW865IYBdhLWcg3wYNZS - Arun K

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接