Client side search with fuse.js

By
Chris Haan

Search is arguably one of the most important elements of a successful website. After all, it doesn't matter if the information is there if you can't find it.  Often, it is useful to implement several search strategies on a site, each of which can be optimized for the specific data being searched. Today, I would like to talk about fuse.js, a nifty little fuzzy search utility that can be easily incorporated into any site.

Fuse.js is a lightweight javascript fuzzy search library written and maintained by Kiro Risk.  As of this time, the current version 3.4.4 weighs in at a mere 10.9 KB. Fuse.js, like many of the best dev tools, is open source, released under the Apache License Version 2.0. In addition to it's small size, fuse.js also has the advantage that it has no external dependencies.

In a nutshell, fuse.js takes as its input a set of data in json format, some configuration information (also json formatted) and a search string.  To be more precise, an instance of the fuse class is instantiated with the input data and config, then the search method of that instance is called with the query as its argument.  The input should be in the form of an array of identically structured json objects since we will be telling fuse.js which parts of each object to consider in the search as a part of the configuration. Fuse.js returns an array of matches, filtered by the query string in accordance with the search settings.  These output results can be the full original objects, or if the records have a unique key, this can be identified in the search configuration and the results can simply be an array of these ids.

To configure fuse.js, you pass in an configuration object when you create your fuse.js instance.  Although there is not a huge number of configuration options, there are enough to tune the search in several ways.  Some options such as "caseSensitive", "tokenize", "location", "threshold" and "keys" allow you to specify exactly how the data will be searched.  These determine what will be taken into consideration when deciding which records are matches. Other configuration options such as "includeScore", "includeMatches" and sort affect the format of the output.  I won't go too deep into the meaning of each of these parameters, but will note that the main parameters determining the "fuzziness" of the search are "location", "distance" and "threshold".

The fuse.js homepage explains all of the parameters in greater detail, but even better, it allows you experiment with them live.  You can either use the sample data included in the page, a list of book title and authors, or paste in your own json formatted data.  As you change the selected configuration options, two output windows are updated in real time, one showing the javascript required to instantiate and run the query and the other showing the search results.  This provides a quick method for experimenting with the various configuration parameters and when you have the parameters tweaked to you liking, you can just copy and paste the configuration block into your code.  

Fuse.js might not make sense for every situation, but can be ideal depending on your search requirements.  I am currently using it in what is essentially a single page app within a larger website. Each user has their own data and the number of records per user is relatively small (currently the maximum size is under 400 records) so fuse.js is more than adequate for my purposes.  What's more, the data that I needed to search was already being loaded in the page as it was using Vue.js to generate the page. Previously, the same search was using Algolia which is a great service, but was overkill for this particular use case. With few records per user, but thousands of total users, the Algolia index was huge and growing steadily.  This, coupled with the fact that this was a convenience feature that not all users needed or used prompted me to seek an alternative and fuse.js was the perfect fit.

Fuse.js worked so well for me that I never tried any of the other javascript search libraries that are out there, but if you find that fuse.js doesn't quite cut it for you, you might give one of the the following a try:  js-search (https://github.com/bvaughn/js-search) by Brian Vaughn or fuzzy (https://github.com/mattyork/fuzzy) by Matt York.