has() / whereHas() fails when custom relationship keys are numeric strings
has() / whereHas() fails when custom relationship keys are numeric strings
Environment
- Laravel: 13.7.0
- mongodb/laravel-mongodb: 5.7.1
- mongodb/mongodb: 2.2.0
Description
has() and whereHas() appear to fail when a relationship uses custom string keys whose values are numeric strings (e.g. "1", "2").
The relationship itself works correctly, but relationship existence queries (has, whereHas) return no results.
Using non-numeric strings (e.g. "item-1") works as expected.
Reproduction
Models
class ParentModel extends Model
{
public function children()
{
return $this->hasMany(ChildModel::class, 'parent_key', 'custom_key');
}
}
class ChildModel extends Model
{
public function parent()
{
return $this->belongsTo(ParentModel::class, 'parent_key', 'custom_key');
}
}Documents
parents
{
"custom_key": "1"
}children
{
"parent_key": "1"
}Working
ParentModel::first()->children;
ParentModel::first()->children()->count();
ChildModel::where('parent_key', '1')->exists();All of the above return the expected results.
Failing
ParentModel::has('children')->get();
ParentModel::whereHas('children')->get();These return an empty collection.
Query log
The generated query contains BSON integers instead of strings:
{
"custom_key": {
"$in": [
{ "$numberInt": "1" }
]
}
}However, the stored values are BSON strings:
{
"custom_key": "1"
}Since MongoDB performs strict type matching, the query returns no results.
Additional observation
If the values are changed from numeric strings to non-numeric strings, for example:
{
"custom_key": "item-1"
}and
{
"parent_key": "item-1"
}then has() and whereHas() work correctly.
This suggests that somewhere during the relationship existence query, numeric strings are being coerced into integers before the $in query is constructed.
Source: mongodb/laravel-mongodb