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
children
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:
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.
has()/whereHas()fails when custom relationship keys are numeric stringsEnvironment
Description
has()andwhereHas()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
Documents
parents
{ "custom_key": "1" }children
{ "parent_key": "1" }Working
All of the above return the expected results.
Failing
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()andwhereHas()work correctly.This suggests that somewhere during the relationship existence query, numeric strings are being coerced into integers before the
$inquery is constructed.