search-index

Logo

A persistent, network resilient, full text search library for the browser and Node.js

View the Project on GitHub fergiemcdowall/search-index

FAQ

How do I create an index?

import { SearchIndex } from 'search-index'
const idx = new SearchIndex({
  name: indexName
})

There is also a file in the dist folder called search-index.x.x.x.js (replace ‘x.x.x’ with version number) that can be referenced from a script tag:

<script type='text/javascript' src='search-index.x.x.x.js'></script>
<script type='text/javascript'>
  import SearchIndex from search-index
  const idx = new SearchIndex({
    name: indexName
  })
  // ...
</script>

How do I get my data into search-index?

You can either import an index, or add documents:

Export/Import an index

// EXPORT an index
const exportFile = await index1.EXPORT()

// IMPORT an index
index2.IMPORT(exportFile)

NOTE: IMPORTing an index completely overwrites any existing index, so if you had an existing index that contained several thousand documents into which you imported an external index that contained one document, then your existing index would now contain one document.

Add documents to an index

// then somewhere else in the code, being aware of asynchronousity
PUT([ /* my array of objects */ ]).then(doStuff)

Can I use another backend like MySQL or Redis?

Yes you can! Because search-index is built on top of abstract-level it is possible to swap out database backends by passing the appropriate store when initialising. Use the Level initialisation option.

Example:

// Use the in-memory MemoryLevel store
import { MemoryLevel } from 'memory-level'
import { SearchIndex } from 'search-index'

const memdownIndex = new SearchIndex({
  Level: MemoryLevel,
  name: indexName
})

How do I get out entire documents and not just document IDs?

Use { DOCUMENTS: true }.

Query that returns document IDs:

SEARCH([ 'search', 'terms' ])

Query that returns documents:

SEARCH([ 'search', 'terms' ], { DOCUMENTS: true })

How do I search on specific fields?

To return hits for all documents containing ‘orange’ in the title field you would do something like this:

QUERY({
  AND: [ 'title:orange' ]
})

// can also be expressed as:
QUERY({
  AND: [{
    FIELD: [ 'title' ],
    VALUE: 'orange'
  }]
})

// or even
QUERY({
  AND: [{
    FIELD: [ 'title' ],
    VALUE: {
      GTE: 'orange',
      LTE: 'orange'
    }
  }]
})

How do I compose queries?

Queries can be composed by nesting SEARCH, AND, NOT and OR clauses as deeply as required. For example:

QUERY({
  OR: [
    {
      AND: [ 'brand:volvo', 'manufacturer:tesla' ]
    },
    'make:bmw'
  ]
})

How do I perform a simple aggregation on a field?

Get a set of document ids per unique field value

const facets = await FACETS({ FIELD: name })

Get counts per unique field value

const facets = await FACETS({ FIELD: name })
  .then(fcts => fcts.map(
    f => ({
      FIELD: f.FIELD,
      VALUE: f.VALUE,
      count: f._id.length
    })
  ))

Define custom “buckets”

const buckets = await BUCKETS ([
  token1,
  token2,
  token3
])

By using QUERY with the appropriate options, you can create aggregations on the set of documents returned by the QUERY.

// also works with BUCKETS
const buckets = QUERY(q, {
  FACETS: [ { FIELD: name } ]
})

How do I make a simple typeahead / autosuggest / matcher

There are of course many ways to do this, but if you just want a simple “begins with” autosuggest, then you can simply use the DICTIONARY function:

const results = await DICTIONARY('b')   // [ 'bananas','branch','brunch' ]
const results = await DICTIONARY('br')  // [ 'branch','brunch' ]
const results = await DICTIONARY('bra') // [ 'branch' ]

Alternatively you can use DICTIONARY to extract all terms from the index and then feed them into some third-party matcher logic.

import FuzzySet from 'fuzzyset'
// ...
const dict = await DICTIONARY()
const fs = FuzzySet()
dict.forEach(d => fs.add(d))
// ...
// fuzzy matching
fs.get(searchTerm)