Монго сортировка по нескольким полям во вложенном массиве

У меня есть коллекция монго с такими документами, как

{
_id : 1abc,
'data' :'blah',
'createdDate' : ISODate("2013-05-26T01:34:10Z"),
'a': [
    {
        _id : a1adas,
        'createdDate' : ISODate("2013-05-26T01:35:10Z"),
        'b':[
                {
                    _id : aadaasd
                    'createdDate' : ISODate("2013-05-26T01:37:10Z"),
                }
            ]
    }
]

}

Мне необходимо отсортировать документы в обратном хронологическом порядке, чтобы документ с самой последней созданной датой на любом уровне был первым.

Пока у меня есть этот запрос, который я не уверен, что работает как ожидалось.

db.collection.find({'data':'blah'}).sort({'createdDate':-1, 'a.createdDate': -1, 'a.b.createdDate': -1 }).explain();

Я хотел бы знать, есть ли более эффективный способ выполнения такого рода.

1 ответ

Ваш запрос не делает то, что вы хотели бы сделать. Сортировка MongoDB по нескольким полям будет обрабатывать каждое поле по очереди, а не все три поля вместе. Например, я вставил несколько тестовых документов в коллекцию, и я выполнил аналогичную сортировку:

> db.numbers.find().sort( { a : -1, b : -1, c : -1 })
{ doc : "doc1", "a" : 13, "b" : 5, "c" : 7 }
{ doc : "doc2", "a" : 12, "b" : 20, "c" : 91 }
{ doc: "doc3", "a" : 2, "b" : 50, "c" : 700 }

"doc3" имеет наименьшее значение a, поэтому оно возвращается последним. Тем не менее, он также имеет наибольшее значение среди всех полей в этом роде, поэтому теоретически нам бы хотелось, чтобы оно было возвращено первым. Мы можем сделать это, используя платформу агрегации MongoDB:

db.numbers.aggregate(
{ $project : { 
    _id : 1, 
    a : 1, 
    maxNum : { $cond: [{ $gte : [ "$b", "$c" ]}, "$b" , "$c" ]} // max of b, c
    }},
{ $project : { 
   _id : 1, 
   maxNum : { $cond: [{ $gte : [ "$a", "$maxNum" ]}, "$a" , "$maxNum" ]} // max of a, b, c 
   }}, 
{ $sort : { maxNum : -1 } } 
)

Этот запрос агрегации преобразует ваши данные в форму, в которой ваш сортировка может быть выполнена правильно. Тем не менее, это не так просто увидеть, как это работает. В настоящее время нет функции.explain() для запросов агрегации.

Другие вопросы по тегам