Skip to content

Supersonic reverse-search engine, featuring a full-fledged DSL, including geofencing capabilities

License

Notifications You must be signed in to change notification settings

kuzzleio/koncorde

Repository files navigation

Codecov Code Quality: Javascript Total Alerts

Koncorde

This module is a reverse-search engine.

Instead of indexing data and searching for them using filters, Koncorde does the opposite: it indexes search filters, and returns the corresponding ones when presented with data.

  • an arbitrary large number of filters can be registered and indexed;
  • whenever data are submitted to Koncorde, it returns the list of indexed filters matching them;
  • Koncorde's filter syntax supports a variety of different matchers, and ways to combine them.

Koncorde can be used in a variety of ways. For instance:

  • as a base of a notification system, where indexed filters are used as user subscriptions: Koncorde tells which JSON objects verify what subscriptions, making it easy to send events to listening users;
  • to verify if JSON objects comply to filters used as validation rules.

Check our full documentation to know more about Koncorde's API, filter syntax, and more.

Quick start example

In the following example, we'll listen to objects containing a position property, describing a geopoint. We want that geopoint to be 500 meters around a pre-defined starting position.

This can be described by the following Koncorde filter:

{
    "geoDistance": {
        "position": {
            "lat": 43.6073913,
            "lon": 3.9109057
        },
        "distance": "500m"
    }
}

All you need to do now is to register this filter to the engine, and use it to test data:

import { Koncorde } from 'koncorde';

const engine = new Koncorde();

const filter = {
    geoDistance: {
        position: {
            lat: 43.6073913,
            lon: 3.9109057
        },
        distance: "500m"
    }
};

const filterId = engine.register(filter);

// Filter Identifiers are seeded. Given the same seed (to be provided to the
// constructor), then the filter IDs stay stable.
console.log(`Filter identifier: ${filterId}`);

// No match found, returns an empty array (distance is greater than 500m)
console.log(engine.test({ position: { lat: 43.6073913, lon: 5.7 } }));

// Point within the filter's scope: returns the list of matched filters
// Here we registered just one of them, so the array contains only 1 filter ID
console.log(engine.test({ position: { lat: 43.608, lon: 3.905 } }));

// No match found, returns an empty array 
// (the geopoint in the provided data is not stored in the tested field)
console.log(engine.test({ not_position: { lat: 43.608, lon: 3.905 } }));

Install

This library is compatible with Node.js version 12.x or higher. Both a C and a C++ compilers are needed to install its dependencies: Koncorde cannot be used in a browser.

Koncorde is compatible with either Javascript or Typescript projects.

To install:

npm install koncorde

Benchmarks

The following results are obtained running node benchmark.js at the root of the projet.

Filter count per tested keyword: 10000

> Benchmarking keyword: equals
  Indexation: time = 0.255s, mem = +39MB
  Matching x 10,320,209 ops/sec ±0.70% (95 runs sampled)
  Filters removal: time = 0.018s

> Benchmarking keyword: exists
  Indexation: time = 0.285s, mem = +20MB
  Matching x 5,047,932 ops/sec ±0.23% (97 runs sampled)
  Filters removal: time = 0.021s

> Benchmarking keyword: geoBoundingBox
  Indexation: time = 0.685s, mem = +-8MB
  Matching x 1,322,528 ops/sec ±0.52% (94 runs sampled)
  Filters removal: time = 0.092s

> Benchmarking keyword: geoDistance
  Indexation: time = 1.052s, mem = +3MB
  Matching x 1,656,882 ops/sec ±0.65% (96 runs sampled)
  Filters removal: time = 0.094s

> Benchmarking keyword: geoDistanceRange
  Indexation: time = 1.551s, mem = +20MB
  Matching x 1,344,257 ops/sec ±2.83% (90 runs sampled)
  Filters removal: time = 0.101s

> Benchmarking keyword: geoPolygon (5 vertices)
  Indexation: time = 0.818s, mem = +-74MB
  Matching x 112,091 ops/sec ±0.54% (97 runs sampled)
  Filters removal: time = 0.098s

> Benchmarking keyword: in (5 random values)
  Indexation: time = 0.974s, mem = +90MB
  Matching x 3,579,507 ops/sec ±2.93% (92 runs sampled)
  Filters removal: time = 0.058s

> Benchmarking keyword: range (random bounds)
  Indexation: time = 0.276s, mem = +-72MB
  Matching x 122,311 ops/sec ±1.28% (96 runs sampled)
  Filters removal: time = 0.074s

(results obtained with node v16.2.0)