Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mongodb 2.6.0-rc2 and PHP 1.4.5 - find _id $in

A simple query like this:

$a = array('_id' => array( '$in' => array_values($ids) ) ); 
var_dump($a);
$cursor2 = $data->find( $a );

works in mongodb 2.4.9, however, in 2.6.0-rc2 returns this:

Type: MongoCursorException
Code: 17287
Message: Can't canonicalize query: BadValue $in needs an array

The output from var_dump:

array(1) {
  ["_id"]=>
  array(1) {
    ["$in"]=>
    array(10) {
      [0]=>
      object(MongoId)#57 (1) {
        ["$id"]=>
        string(24) "52214d60012f8aab278eacb6"
      }
      [1]=>
      object(MongoId)#58 (1) {
        ["$id"]=>
        string(24) "52214d60012f8aab278eaca8"
      }
      [2]=>
      object(MongoId)#59 (1) {
        ["$id"]=>
        string(24) "52214d60012f8aab278eaca7"
      }
   }
}
}

I wonder if this is a Mongo or PHP related?

THanks!

like image 471
Pavel Avatar asked Mar 30 '14 18:03

Pavel


2 Answers

This... is a change in MongoDB 2.6.0, no longer accepting bson object in the $in clause.

This particular issue is being tracker as a PHP driver bug at https://jira.mongodb.org/browse/PHP-1051

The MongoDB PHP Driver will serialize an PHP Array into BSON Array (accepted by the $in operator) when the PHP array is: Sequential numerically indexed, starting from 0

This means that if you have an array like:

$array = array($id0, $id1, $id2, $id3, $id4);

and then you

unset($array[0]);

You actually wind up with:

$array = array(1 => $id1, 2 => $id2, 3 => $id3, 4 => $id);

Which does not start with index 0. The MongoDB PHP driver therefore converts this into a BSON Object... Leading to validation error in MongoDB as it expected an array.

Now, since the MongoDB PHP driver does not do parse your MongoDB query we cannot know which array should be exempted from this serialization rule.

The workaround is, as mentioned above, is to ensure your PHP arrays are numerically indexed, starting from 0. The easiest way to do that is to run

array_values($values);
like image 75
bjori Avatar answered Nov 18 '22 18:11

bjori


After debugging it with mongo, I've noticed the following:

... query: { _id: { $in: { 0: ObjectId('52214d60012f8aab278eaad1') ...

but it should be

... query: { _id: { $in: [ ObjectId('52214d60012f8aab278eaad1') ...

So, I would suggest doing array_values($VAR) before calling $in, I'm guess Mongo 2.4.9 is more lenient to the fact that $ids can be either object or an array, make sure you use arrays in mongo 2.6 ;)

like image 37
Pavel Avatar answered Nov 18 '22 17:11

Pavel