7

我有一个集合,我使用 $query 从中获取特定类型的用户
然后我需要根据 user_id 升序对它们进行排序并将它们限制为 2000

从这些我需要最大 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)
4

5 回答 5

7

您不能先进行排序,然后再进行限制,然后再进行排序。Cursor 对象就是这样,它不会运行查询,直到您迭代到第一个结果,通过getNext()该结果可以手动运行或在foreach循环中运行,不仅如此,而且sort只是对象的一个​​属性,因此进行两种排序只会覆盖该属性.

实现您的目标的最佳方法是:

$doc = $collection->find($query)->sort(array('user_id' => 1))
       ->skip(1999)->limit(1)->getNext();

这将始终选择user_id组中最高的(在这种情况下出现在最后),这将给出与进​​行两种排序相同的结果。

于 2013-01-20T14:45:41.247 回答
3

使用skip()怎么样:

$cursor = $collection   ->find($query)  
        ->sort(array('user_id'=>1))   
        ->limit(2000)                
        ->skip(1999);
于 2013-01-20T11:52:05.693 回答
0

sort-limit-sort-limit 方法背后的原因是什么?

你不能就这样吗

$cursor = $collection ->find($query)
            ->sort(array('user_id'=>-1))
            ->limit(1);

编辑:此外,只有最后sort应用于光标的效果。(这一行出现在pymongodocs here中,这是有道理的。)

于 2013-01-20T11:11:56.570 回答
0

我在最新版本中使用以下代码:

$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);

那行得通。也许你应该在新版本中尝试一下。

于 2014-11-07T08:29:32.200 回答
0

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
    ),
));
于 2016-09-02T12:15:56.873 回答