0.0.1 • Published 5 years ago

pi-redredisearch v0.0.1

Weekly downloads
5
License
-
Repository
github
Last release
5 years ago

RedRediSearch

RedRediSearch is a Node.js wrapper library for the RediSearch Redis module. It is more-or-less syntactically compatible with Reds, another Node.js search library. RedRediSearch and RediSearch can provide full-text searching that is much faster than the original Reds library (see Benchmarks).

Upgrading

If you are upgrading from Reds, you'll need to make your createSearch asynchronous and re-index your data. Otherwise, your app-level logic and code should be compatible.

Installation

  $ npm install redredisearch

Example

The first thing you'll want to do is create a Search instance, which allows you to pass a key, used for namespacing within RediSearch so that you may have several searches in the same Redis database. You may specify your own node_redis instance with the redredisearch.setClient function.

redredisearch.createSearch('pets',{}, function(err, search) {
  /* ... */
});

You can then add items to the index with the Search#index function.

var strs = [];
strs.push('Tobi wants four dollars');
strs.push('Tobi only wants $4');
strs.push('Loki is really fat');
strs.push('Loki, Jane, and Tobi are ferrets');
strs.push('Manny is a cat');
strs.push('Luna is a cat');
strs.push('Mustachio is a cat');

redredisearch.createSearch('pets',{}, function(err,search) {
  strs.forEach(function(str, i){ search.index(str, i); });
});

To perform a query against the index simply invoke Search#query() with a string, and pass a callback, which receives an array of ids when present, or an empty array otherwise.

search
  .query('Tobi dollars')
  .end(function(err, ids){
    if (err) throw err;
    console.log('Search results for "%s":', query);
    ids.forEach(function(id){
      console.log('  - %s', strs[id]);
    });
  });

By default, queries are an intersection of the search words. The previous example would yield the following output since only one string contains both "Tobi" and "dollars":

Search results for "Tobi dollars":
  - Tobi wants four dollars

We can tweak the query to perform a union by passing either "union" or "or" to Search#type() in redredisearch.search() between Search#query() and Search#end(), indicating that any of the constants computed may be present for the id to match.

search
  .query('tobi dollars')
  .type('or')
  .end(function(err, ids){
    if (err) throw err;
    console.log('Search results for "%s":', query);
    ids.forEach(function(id){
      console.log('  - %s', strs[id]);
    });
  });

The union search would yield the following since three strings contain either "Tobi" or "dollars":

Search results for "tobi dollars":
  - Tobi wants four dollars
  - Tobi only wants $4
  - Loki, Jane, and Tobi are ferrets

RediSearch has an advanced query syntax that can be used by using the 'direct' search type. See the RediSearch documentation for this syntax.

search
  .query('(hello|hella) (world|werld)')
  .type('direct')
  .end(function(err, ids){
    /* ... */
  });

Also included in the package is the RediSearch Suggestion API. This has no corollary in the Reds module. The Suggestion API is ideal for auto-complete type situations and is entirely separate from the Search API.

var suggestions = redredisearch.suggestion('my-suggestion-list');

suggestions.add(
  'redis',                                            // add 'redis'
  2,                                                  // with a 'score' of 2, this affects the position in the results, higher = higher up in results
  function(err,sizeOfSuggestionList) { /* ... */ }    // callback
);
suggestions.add(
  'redisearch',                                       
  5,
  function(err,sizeOfSuggestionList) { /* ... */ } 
);
suggestions.add(
  'reds',                                       
  1,
  function(err,sizeOfSuggestionList) { /* ... */ } 
);

/* ... */

sugggestions.get(
  're',                                               // prefix - will find anything starting with "re"
  function(err, returnedSuggestions) {
    /* returnedSuggestions is set to [ "redisearch", "redis", "reds" ] */
  }
);

sugggestions.get(
  'redis',                                            // prefix - will find anything starting with "redis", so not "reds"
  function(err, returnedSuggestions) {
    /* returnedSuggestions is set to [ "redisearch", "redis" ] */
  }
)

There is also a fuzzy opt and maxResults that can either be set by chaining or by passing an object in the second argument in the constructor.

API

redredisearch.createSearch(key, options, fn) : Search
redredisearch.setClient(inClient)
redredisearch.createClient()
redredisearch.confirmModule(cb)
redredisearch.words(str) : Array
redredisearch.suggestionList(key,opts) : Suggestion
Search#index(text, id[, fn])
Search#remove(id[, fn]);
Search#query(text, fn[, type]) : Query
Query#type(type)
Query#between(str)
Query#end(fn)
Suggestion#fuzzy(isFuzzy)
Suggestion#maxResults(maxResults)
Suggestion#add(str,score,fn)
Suggestion#get(prefix,fn)
Suggestion#del(str,fn)

Examples:

var search = redredisearch.createSearch('misc');
search.index('Foo bar baz', 'abc');
search.index('Foo bar', 'bcd');
search.remove('bcd');
search.query('foo bar').end(function(err, ids){});

Benchmarks

When compared to Reds, RedRediSearch is much faster at indexing and somewhat faster at query:

Indexing - documents / second

ModuleTinySmallMediumLarge
Reds12275100
RediRediSearch1,2565011325

Query - queries / second

Module1 term2 terms / AND2 terms / OR3 terms / AND3 terms / ORLong* / ANDLong* / OR
Reds8,7548,7658,3897,6227,1931,6491,647
RedRediSearch10,95512,94510,05412,7698,3896,45612,311

The "Long" query string is taken from the Canadian Charter of Rights and Freedoms: "Everyone has the following fundamental freedoms: (a) freedom of conscience and religion; (b) freedom of thought, belief, opinion and expression, including freedom of the press and other media of communication; (c) freedom of peaceful assembly; and (d) freedom of association." (Used because I just had it open in another tab...)

Next steps

  • More coverage of RediSearch features
  • Tests
  • Better examples

License

(The MIT License)