dannydinges's avatar

Laravel Scout Eager Loading Relationships

I'm using the following to eager load relations using scout

$users = User::search($query)->paginate(25); $users->load('relation');

Problem is it no longer returns a LengthAwarePaginator when using the load. If I don't use the load it will return a LengthAwarePaginator.

Laravel 5.4 and Scout 3.0. Any ideas?

0 likes
9 replies
Dreferr's avatar

I'm also running into issues as well. I'm using tntsearch with laravel scout.

digital@jfd.co.uk's avatar

Hi All,

Unfortunately it seems that scout results aren't relational at the moment. But you can amend what is being placed in your index via the toSearchableArray() method.

    /**
     * Get the indexable data array for the model.
     *
     * @return array
     */
    public function toSearchableArray()
    {
        $array = $this->toArray();

        $array['county'] = $this->county['name'];

        return $array;
    }

In this instance, my user object has a county associated by ID in a lookup table.

I am pulling that data via the eloquent relationship and adding that as a property to the array that is being pushed up to algolia via scout.

https://laravel.com/docs/5.4/scout#configuring-searchable-data

1 like
robbydooo's avatar

@jamesforddesign have you found anyway to retrieve this data using scout search though once it is indexed? It only seems to be available using raw().

I am trying to find a way of making the additional data sent to algolia available once scout rehydrates the model. This is also useful for the additional data sent back by algolia for distance around a geosearch for example.

Anyone have any ideas?

Reback's avatar
/**
 * Get the indexable data array for the model.
 *
 * @return array
 */
public function toSearchableArray()
{
    $array = $this->with("brand")->with("category")->with("productSkus")->where("id", $this->id)->first()->toArray();
    return $array;
}

Laravel : php artisan scout:import "" will index models one by one.

tang.chanrith's avatar

I am using Laravel Scout with tntsearch, and this how I solve the problem.

// first statement will return id list of matched record
$ids = User::search($query)->keys()->toArray();
$users = User::with('relationship')->whereIn('id', $ids)->get();
2 likes
tovitch's avatar

Laravel Scout provide a nice way to eager load relations.

$users = User::search($query)->query(function ($builder) {
    $builder->with('relation');
})->paginate(25);

The query method callback is executed just before getting the requested models from the database, in the Searchable trait :

/**
 * Get the requested models from an array of object IDs.
 *
 * @param  \Laravel\Scout\Builder  $builder
 * @param  array  $ids
 * @return mixed
 */
public function getScoutModelsByIds(Builder $builder, array $ids)
{
    $query = static::usesSoftDelete()
        ? $this->withTrashed() : $this->newQuery();

    if ($builder->queryCallback) {
        call_user_func($builder->queryCallback, $query); // here
    }

    return $query->whereIn(
        $this->getScoutKeyName(), $ids
    )->get();
}
11 likes
MiguelStevens's avatar

This doesn't seem to be working? The callback is ignored, is there anything else that needs to happen to make this work?

prokofiev's avatar

use query() method

Product::search($query)->query(function (Builder $builder) {
    $builder->with(['category', 'brand']);
})->simplePaginate()
3 likes

Please or to participate in this conversation.