У меня есть коллекция, из которой я получаю определенный тип пользователей, используя $ query
Затем мне нужно отсортировать их в соответствии с user_id по возрастанию и ограничить их до 2000
Из них мне нужен max user_id, поэтому я сортирую их в порядке убывания и ограничиваю 1.
Но этот второй сорт забывает предел 2000 и сортирует по всему курсору из find ().
Любая работа вокруг?
$cursor = $collection ->find($query) // too many entries ->sort(array('user_id'=>1)) // go ascending ->limit(2000) // got our limited qouta ->sort(array('user_id'=>-1)) // go descending to get max ->limit(1); // the one with max(user_id)
Вы не можете сделать своего рода, а затем лимит, а затем сорт. Объект Cursor точно такой, и он не будет запускать запрос до тех пор, пока вы не перейдете к первому результату через getNext()
который либо запускается вручную, либо внутри цикла foreach
не только, но и sort
– это просто свойство объекта, поскольку оно делает два sorts просто перезаписывает свойство.
Лучший способ добиться того, что вы ищете:
$doc = $collection->find($query)->sort(array('user_id' => 1)) ->skip(1999)->limit(1)->getNext();
Это всегда будет выбирать самый высокий user_id
(который встречается в конце этого типа) группы, что даст те же результаты, что и два вида.
Как насчет использования skip ():
$cursor = $collection ->find($query) ->sort(array('user_id'=>1)) ->limit(2000) ->skip(1999);
В чем причина подхода к методу сортировки-лимита-сортировки?
Разве ты не можешь просто сделать
$cursor = $collection ->find($query) ->sort(array('user_id'=>-1)) ->limit(1);
EDIT: Также действует только последний sort
применяемый к курсору. (Эта строка присутствует здесь в pymongo
docs, что имеет смысл.)
Я использую следующий код в php5 и последней версии mongodb :
$doc = $collection->find($query)->sort(array('user_id' => 1)) ->skip(1999)->limit(1)->getNext();
Он перестает работать, когда я использую ->skip(1999)->limit(1)
после sort()
Курсор $doc
дает мне значения. Я попытался сделать это:
$doc = $collection->find($query)->sort(array('user_id' => 1)) $doc = $doc->skip(1999)->limit(1);
Это сработало. Может быть, вы должны попробовать это в новых версиях.
Ответ Sammaye верен.
Вы все еще можете достичь того, чего хотите. Вы можете использовать структуру агрегации, поскольку она выполняет один этап после другого этапа и так далее.
$doc = $collection->aggregate(array( array( '$match' => $query, ), array( '$sort' => array( 'user_id'=> 1 ), ), array( '$limit' => 2000 ), array( '$sort' => array( 'user_id'=> -1 ), ), array( '$limit' => 1 ), ));