Монго сортировка по нескольким полям во вложенном массиве
У меня есть коллекция монго с такими документами, как
{
_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() для запросов агрегации.