wire-elements / spotlight

Livewire component that brings Spotlight/Alfred-like functionality to your Laravel application.
MIT License
912 stars 71 forks source link

Ability to customize Fuse search options #67

Open devcircus opened 2 years ago

devcircus commented 2 years ago

Issue

I've noticed that some of my search results aren't appearing in the spotlight search results. They're actually returned as dependencyQueryResults, which can be confirmed in alpinejs devtools, but they don't make it through Fuse to appear in the spotlight result list. By default, Fuse places importance on the beginning of the field that is being searched. Since the match is towards the end of the searched string, it is being ignored.

Example String being searched: "TTU/JH COMM COLLEGE DESIGN CATALOG SAMPLES O# 492026578-7,8,9"

if my input search query is "492026578", this result doesn't make it to the result list. It IS however, part of the query results, but Fuse skips over it because the query string is at the end of the searched string.

Solution

Provide a way to customize the Fuse fuzzy matching options like location, distance, ignoreLocation, and threshold.

If I manually edit the spotlight.js file and set ignoreLocation to true, then the result shows on the page as expected.

I could attempt a PR, but may take a while. I understand if you don't want to start tying your package down to the Fuse fuzzy search implementation, but maybe there's a way to add options that can be translated to those Fuse options. Then again, you may not want spotlight to be concerned with that stuff at all. If so, I understand.

Thanks for this great component.

PhiloNL commented 2 years ago

I will look into this, for now, using dependency synonyms should resolve the issue: https://github.com/wire-elements/spotlight/issues/63#issuecomment-979471413

devcircus commented 2 years ago

Ah thanks! Had not even thought about synonyms.

devcircus commented 2 years ago

Ok, yeah I think there was a misunderstanding, maybe on my part, but I'm not searching for a command. I have a command that queries my database.

It searches the database based on my input, the returns results for me to choose from. It's just not showing all of the results that it should. If I change the fuse threshold to 0.6 from 0.3, or if I just set ignoreLocation: true, then it returns all of the results that it should. Otherwise it skips some results.

The initial query actually works, I can see the found results in alpinejs devtools, but then they're filtered through Fuse, and some get left out unless I make the changes listed above.

I'll close for now as this is more of a feature request than an issue with the package.

Thanks!

devcircus commented 2 years ago

Details

    /**
     * Define dependencies for the command.
     */
    public function dependencies(): null | SpotlightCommandDependencies
    {
        return SpotlightCommandDependencies::collection()
            ->add(SpotlightCommandDependency::make('artOrder')->setPlaceholder('Type the title of the order, or a partial title.'));
    }

    /**
     * Search Orders with the given query.
     */
    public function searchArtOrder(string $query): Collection
    {
        return ArtOrder::whereLike('title', $query)
            ->get()
            ->map(function (ArtOrder $artOrder) {
                return new SpotlightSearchResult(
                    $artOrder->slug,
                    $artOrder->title,
                    null
                );
            });
    }

    /**
     * When all dependencies have been resolved the execute method is called.
     * You can type-hint all resolved dependency you defined earlier.
     */
    public function execute(Spotlight $spotlight, ArtOrder $artOrder)
    {
        $spotlight->emit('openModal', 'voucher-modal', [
            'voucher' => $artOrder->toArray(),
        ]);
    }

The searchArtOrder method actually returns all of the expected results. However, before the results are displayed in the view, they are filtered through Fuse, which removes some results. For instance, if the title is very long and the match occurs near the end of the title, Fuse ignore it.

eg. "This is a very long title that has the match that I am searching for located at the very end 447982456."

So if my input is "447982456", then the above will not be passed to the view.

devcircus commented 2 years ago

Reopening to clarify with the details above. Will close later.

aitordri commented 2 years ago

Same "issue" here

daylightstudio commented 2 years ago

I've run into the same issue. Changing the threshold to something higher like the default .6 fixed my problem albeit requires recompiling the js. Could the threshold just be set to 1.0 since the results should be dictated on the PHP side?