laravel-scout-typesense-driver icon indicating copy to clipboard operation
laravel-scout-typesense-driver copied to clipboard

Unable to sort

Open robjbrain opened this issue 1 year ago • 4 comments

Description

At present it doesn't seem possible to sort, or if it is it's not documented anywhere.

Steps to reproduce

Setup on a model in this example Post and try the following:

Post::search(['q' => $searchTerm, 'sort_by' => 'created_at:asc'])

Expected Behavior

I would expect the results to be ordered by the created_at attribute in ascending order

Actual Behavior

Instead the following error message is show:

Request Malformed: Parameter q is required.

Metadata

Typesense Driver Version: 5.2.4

robjbrain avatar May 02 '23 03:05 robjbrain

Hi @robjbrain, The search method is not accepting an array, it accepts a search query string.

So you should use this as following: Post::search($searchTerm)->orderBy('created_at', 'asc');

If you have any further questions, please let us know.

karakhanyans avatar Jun 05 '23 06:06 karakhanyans

Hi @robjbrain, have you tried the solution that we suggested? Do you have any other problems using the drivers?

karakhanyans avatar Jun 16 '23 06:06 karakhanyans

Hey sorry not replying sooner. I realised later that you're reliant on Scout to only accept a string, but that this is pretty limiting.

The orderBy syntax isn't documented in the readme for this package. A quick test shows it's working.

However at the moment i'm exclusively using the driver using "SearchMulti" to allow more advanced search.

e.g.

            $filter = ['status:=enabled'];
            if ($forumId = $request->input('forum_id')) {
                $filter[] = 'forum_id:='.$forumId;
            }

            $rawResults = Topic::search('')->searchMulti(
                [
                    [
                        'collection' => 'content',
                        'q' => $searchTerm,
                        'sort_by' => '_text_match:desc,created_at:desc',
                        'per_page' => 30,
                        'filter_by' => implode(' && ', $filter)
                    ]
                ]
            ))->raw();

            $ids = Arr::pluck(data_get($rawResults, 'results.0.hits', []), 'document.id');
            
            if ($ids) {
                $results = Topic::query()
                    ->find($ids)
                    ->sortBy(function(ContentItem $item) use ($ids) {
                        return array_search($item->getKey(), $ids);
                    });
            } else {
                $results = collect();
            }

If there isn't a better way of doing the above i'd be all ears. But it's not clear from your docs. It does feel like a very dirty hack though.

robjbrain avatar Jun 16 '23 06:06 robjbrain

@robjbrain you can rewrite it like this


$results = Topic::search($searchTerm)
            ->where('status', 'enabled')
            ->where('forum_id', $request->input('forum_id'))
            ->orderBy('created_at', 'desc')
            ->paginate(30);

karakhanyans avatar Jun 27 '23 09:06 karakhanyans