Search code examples
laraveleloquenteloquent-relationship

Laravel Eloquent returns elements related to the first document only, when using with() + take() methods


i'm trying to get user documents along with first three related meeting documents.

User::with(
    [
        'meetings' => function($query) {
            $query->take(3);
        }
    ]
)->get();

user-meeting relation in App\Models\User.php:

public function meetings(){
    return $this->hasMany(Meeting::class);
}

but as a result, i only get meetings related to the first user:

[
  {
    "_id": "63123a4906650000d2006de2",
    ...
    "meetings": [
      {
        "_id": "63123e0590530000860042bd",
        "user_id": "63123a4906650000d2006de2",
        "start_time": "2022-08-29T12:00:00.000000Z",
        "updated_at": "2022-09-02T17:31:49.601000Z",
        "created_at": "2022-09-02T17:31:49.601000Z"
      },
      {
        "_id": "63123e0590530000860042be",
        "user_id": "63123a4906650000d2006de2",
        "start_time": "2022-08-29T12:15:00.000000Z",
        "updated_at": "2022-09-02T17:31:49.602000Z",
        "created_at": "2022-09-02T17:31:49.602000Z"
      },
      {
        "_id": "63123e0590530000860042bf",
        "user_id": "63123a4906650000d2006de2",
        "start_time": "2022-08-29T12:30:00.000000Z",
        "updated_at": "2022-09-02T17:31:49.603000Z",
        "created_at": "2022-09-02T17:31:49.603000Z"
      }
    ]
  },
  {
    "_id": "63123af290530000860042b2",
    ...
    "meetings": [
      
    ]
  },
  {
    "_id": "63123b0c90530000860042b5",
    ...
    "meetings": [
      
    ]
  }
]

without using take(), all the related meeting documents are loaded.

i'm using jenssegers-mongodb package for laravel-mongodb connection, but the issue also occurs on vanilla eloquent.

Solution

  • just like @apokryfos suggested, the take() eloquent method just adds 'limit' word at the end of the query. this type of query is more complex and isn't supported by vanilla eloquent.

    fortunately, there is an additional package called eloquent-eager-limit, which helps with this problem. in order to make it work, install that package by using composer require staudenmeir/eloquent-eager-limit command and put use \Staudenmeir\EloquentEagerLimit\HasEagerLimit; line inside both parent and children model classes.

    sadly, mongodb isn't supported and there seem to be no efficient way to achieve this when using mongodb. some options that come to my mind are:

    1. writing a query without the help of eloquent, using DB::query() for example,
    2. retrieving all records, displaying or mapping ones that are needed,
    3. writing your own package :D