How to use usort to sort MongoDB query result

Tags: , , , ,



Trying to sort array present in object but getting error usort() expects parameter 1 to be array I have not found any useful solution for this error on anywhere, How can I sort my array[detail] by total array elements count.

Here is my code –

$query = new MongoDBDriverQuery($filter, $options);
$cursor = $manager->executeQuery("DB.col", $query);
foreach($cursor as $row) {
  foreach($row->detail as $item) {
    function cmp($a, $b) {
      return $a['detail'] > $b['detail'];
    }
    usort($row, "cmp");
  }
} 

Schema of my array:

array(
    [0]=>stdclass object( 
        [_id] => MongoDBBSONObjectId Object (
                    [oid] => 5f55f95815a8508e2deac8dd
                )
        [Date] => 9/12/2020
        [title] => ram
        [roll.n] => 5
        [detail] => Array(
            [0] => stdclass object( 
                [title] => John
                [id] =>55
                [class] => six)
            [1] => stdclass object( 
                [title] => Doe
                [id] =>550
                [class] => six)
            [2] => stdclass object( 
                [title] => Jean
                [id] =>9
                [class] => one)
            [3] => stdclass object( 
                [title] => AI
                [id] =>90
                [class] => one)
            )
    )

    [1]=>stdclass object( 
        [_id] => MongoDBBSONObjectId Object (
                [oid] => 5f
        )
        [title] => sunny
        [roll.n] => 50
        [detail] => Array(
            [0] => stdclass object ( 
                [title] => lilly
                [id] =>551
                [class] => six)
            [1] => stdclass object( 
                [title] => Doel
                [id] =>550
                [class] => six)
            [2] => stdclass object( 
                [title] => rehaman
                [id] =>9
                [class] => one
        )
    )
)

Answer

The executeQuery method returns a MongoDBDriverCursor. It implements the Traversable interface so you are allowed to do foreach on it. This might have confused you to think it is an array. It’s actually not.

To do usort on the result, you need to first turn the cursor into an array. Then, if I understand correctly, you are to sort the rows by the size of their ‘detail’ array like this:

$query = new MongoDBDriverQuery($filter, $options);
$cursor = $manager->executeQuery("DB.col", $query);
$rows = $cursor->toArray();

usort($rows, function ($a, $b) {
  return sizeof($a->detail) <=> sizeof($b->detail);
});

return $rows;

Note: if the order is reversed, simply swap the $a->detail and $b->detail in the comparison function of usort() call.

If you’re not using PHP 7, you might not have the spaceship operator <=> to use with. Simply use this comparison function instead:

usort($rows, function ($a, $b) {
  if (sizeof($a->detail) == sizeof($b->detail)) {
    return 0;
  }
  return (sizeof($a->detail) > sizeof($b->detail)) ? 1 : -1;
});

P.S. You should really upgrade to PHP 7. PHP 5.6 has been dropped from support for years. It’s not as performant and less secure.



Source: stackoverflow