mongodb / laravel-mongodb

A MongoDB based Eloquent model and Query builder for Laravel (Moloquent)

Home Page:https://www.mongodb.com/compatibility/mongodb-laravel-integration

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

ObjectId in query builder not working

Sh1d0w opened this issue · comments

I have a Laravel scope that adds condition to a model globally.

$builder->where(['rankedSeason' => new MongoDB\BSON\ObjectId(self::$activeSeasonId)]);

However it gets translated and casted to string when I inspect the query that runs:

rankedMatches.countDocuments(
  { "$and" :[{"player":"e908fe9e-97a6-4dc2-b1ff-55c5b9a87ce2"},{"player":{"$ne":null}},{"rankedSeason":"6555d1f82039d742bfbcfa70"}] },
  []
)

It should cast it to ObjectId instead.

What is your laravel-mongo package version?

Hi, I am using

"mongodb/laravel-mongodb": "^4.0.0-rc1"

Can you test it using 4.1 version?

@hans-thomas just tried with 4.1.x-dev 1c2d1fe same issue there. Thanks for looking into this!

I don't see any error in Builder class. I guess your rankedSeason is stored as a string in the DB and that's why you're getting empty results.
I wrote this test and it's passed.

// Both string
$objectId = (string)(new ObjectId());
$user = User::create(['name' => 'Hans Thomas', 'rankedSeason' => $objectId]);

$query = User::query()->where('rankedSeason', $objectId);
self::assertSame($user->_id, $query->first()->_id);

// Or both ObjectId instances
$objectId = new ObjectId();
$user = User::create(['name' => 'Hans Thomas', 'rankedSeason' => $objectId]);

$query = User::query()->where('rankedSeason', $objectId);
self::assertSame($user->_id, $query->first()->_id);

But if the stored and queried rankedSeason data types weren't the same, it wouldn't pass.

$objectId = (string)(new ObjectId());
$user = User::create(['name' => 'Hans Thomas', 'rankedSeason' => $objectId]);

$query = User::query()->where('rankedSeason', new ObjectId($objectId));
self::assertSame($user->_id, $query->first()->_id);

If you think when you pass the rankedSeason as an ObjectId but it's a string in the query log, I recommend using toMql() to see the exact created mql.

$objectId = new ObjectId();
User::create(['name' => 'Hans Thomas', 'rankedSeason' => $objectId]);

DB::enableQueryLog();
$query = User::query()->where('rankedSeason', $objectId);
dump($query->toMql());
$query->get();
dd(DB::getQueryLog());

// dump's output
array:1 [
  "find" => array:2 [
    0 => array:1 [
      "rankedSeason" => MongoDB\BSON\ObjectId {#1292
        +"oid": "655b45c75a6e9ae8c605da42"
      }
    ]
    1 => array:1 [
      "typeMap" => array:2 [
        "root" => "array"
        "document" => "array"
      ]
    ]
  ]
]

// dd's output
array:1 [
  0 => array:3 [
    "query" => "users.find({"rankedSeason":"655b45c75a6e9ae8c605da42"},{"typeMap":{"root":"array","document":"array"}})"
    "bindings" => []
    "time" => 1.05
  ]
]