Vue: Fulltext search your Vuex store with MiniSearch

Last modified Sep 16 2019 13:20 by Kees de Kooter

Adding full text search to an application and especially nifty features like autocomplete has always been a quite tedious job. The index had to be configured at the backend. APIs needed to be written. Performance was always a concern. Not to mention security.

Why not do all of this on the client side acting on the data the user has in his local store? A brilliant little library called MiniSearch by Luco Ongaro makes this possible.

Fulltext indexing in 6 lines of code!

// Initalize MiniSearch with a schema
const miniSearch = new MiniSearch({fields: ['type', 'title', 'subtitle', 'body']})

// Keep a copy of the indexed documents - we need this if we want to remove or update a document
let documents = new Map()

function indexDocument(document) {
    // Remove first if it already exists
    if (documents.get(document.id)) {
      miniSearch.remove(documents.get(document.id)
  }
  miniSearch.add(document)
  document.set(document.id, document)
}

function search(query) {
    return miniSearch(query, {fuzzy: 1, combineWith: 'AND'})
      .map(hit => documents.get(hit.id))    
}

export { indexDocument }

Hook things up to your Vuex store

Vuex is extensible with plugins that can intercept events taking place in the store.

import { indexDocument } from './search'

export const searchPlugin = store => {

    store.subscribe((mutation, state) => {
      if (mutation.type === 'note') {
        indexDocument(note)    
    }
  })
}

And of course don't forget to let Vuex know to use this plugin:

import { searchPlugin } from './search-plugin'

export default new Vuex.Store({
    ...
  plugins: [searchPlugin]
}

That's about it. From a searchbox in your application you can now call search and populate a search results list.