RoboRobok's avatar

Laravel Scout and with()

I'm using Laravel Scout to search my records with Algoria. As a result, Laravel creates a database query like this:

SELECT * FROM table WHERE id IN (3, 7, 13)

Is there any way to alter this query? I want to use with() to get some related data too. Or should I extend some class to do it?

0 likes
23 replies
RoboRobok's avatar

Is this the only way? For better flexibility, I'd rather prefer to have a normal Builder out of this Scout operation. Scout's Builder is more limited.

jekinney's avatar

Ultimately it really the same thing. Either way same queries will be run.

RoboRobok's avatar

@jekinney I know load() is the same, because it's Collection's method, not Builder's. I mean that I would like to get a Builder instance after I take Scout's results, because I have several other ways of getting records in this code piece. I have a Service Provider that does affect the Builder instance some way after this. But it doesn't work on Scout's Builder, because this one is very limited. It might be impossible to take a classic Builder out of it though, because Scout's results are ordered by relevance.

RoboRobok's avatar

@lars6 Yes, like @jekinney said, you can do it via load() method. The only difference is that load() works on Collection instance and with() works on Builder instance. So, to use load() you get results first and then load relations. For now, I don't think there is any easy way to load relations first.

1 like
Lars-Janssen's avatar

@jekinney that's nice. But it does not work for me -_-

public function toSearchableArray()
{
    $array = $this->with('forum')->toArray();
    return $array;
}

The forum relation is correct I use it in other places in my application and that works fine. Any idea?

RoboRobok's avatar

@lars6 The point of toSearchableArray() is to define what is being sent to search provider (like Algolia). I don't think that's what you are looking for.

1 like
RoboRobok's avatar

I think we need to stick to load() until Builder returned by search() is more alike normal Builder. I am personally okay with load().

Lars-Janssen's avatar

@RoboRobok Hmm how could I do that?

I've this:


return Message::search($search)->paginate(4);

And I tried this:

return Message::search($search)->load('forum')->paginate(4);

Or do you mean this:


public function toSearchableArray()
{
       $array = $this->load('forum')->toArray();
       return $array;
}

But that does not work /:

jekinney's avatar
return Message::search($search)->paginate(4)->load('forum');
1 like
RoboRobok's avatar

Try this :)

return Message::search($search)->paginate(4)->load('forum');

After search() you are with Scout's Builder. load() method is part of regular Collection class, which you have after you either get() or paginate().

2 likes
mevlutozdemir's avatar

@RoboRobok Not exactly. In your solution it returns an Collection. In my solution it returns a LengthAwarePaginator :D

1 like
JustSt's avatar

So what shall I do If I want to search the matched text among all models? Currently I'm running the search method on all the models. @mevlutozdemir @lars6

asolopovas's avatar

In my case it does not return paginater I just simply gets the amount of elements I specify in paginate method parameters.

Reback's avatar

@jekinney Your code is almost close the answer. The code should be

/**
 * 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.

Please or to participate in this conversation.