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

whereHas issue

neilmarsland opened this issue · comments

  • Laravel-mongodb Version: 4.1
  • PHP Version: 8.3.0
  • Database Driver & Version: mongodb

Description:

I have a leagues collection.

{
  "_id": {
    "$oid": "658e9c7d9ce7b199fa555269"
  },
  "type": "CUPMATCH",
  "api_id": 75,
  "name": "World Cup",
  "country_id": {
    "$oid": "658e9c7d9ce7b199fa555268"
  }
}

And Countries Collection

{
  "_id": {
    "$oid": "658e9c7d9ce7b199fa555268"
  },
  "name": "International",
  "main_area": {
    "$oid": "658e9c7d9ce7b199fa555267"
  },
  "flag": "https://football.bongdalu4.com/Image/info/images/164454845888.png"
}

League Model is has relationship with Country

public function country()
   {
       return $this->belongsTo(Country::class, 'country_id');
   }

When I query with whereHas country name is China:

$query = League::with("country")->whereHas('country', function($query){
            $query->where('name', 'LIKE', "%China%");
        });

If return empty collection.

Expected behaviour

It should return all of league in China Country

Actual behaviour

Logs: Insert log.txt here (if necessary)

Hello, this kind of filter requires a $lookup that is not implemented in this library. You can use a raw aggregation pipeline, but the performance will not be optimal:

use MongoDB\BSON\Regex;
use MongoDB\Collection;

League::raw(function (Collection $collection) {
    return $collection->aggregate([
        [
            '$lookup' => [
                'from' => 'countries',
                'localField' => 'country_id',
                'foreignField' => '_id',
                'as' => 'country_info'
            ]
        ],
        [
            '$match' => [
                'country_info.name' => new Regex('China', 'i')
            ]
        ],
        [
        '$project' => [
            'country_info' => 0,
        ],
    ]);
});

The League model should be populated.

Also, the MongoDB modeling strategy is different from tabular databases, you can denormalize the country name in the leagues documents when they are saved. Learn about Map Schema Relationships