level-match-map

Use level-match-index

Index your database objects in the way they will be rendered. Follows the JSON Context matcher pattern. Datasources generated from matchers, then watch for realtime changes.

npm install level-match-map
2 downloads in the last week
4 downloads in the last month

Match Map for LevelDB

Index your database objects in the way they will be rendered. Follows the JSON Context matcher pattern allowing datasources to automatically be generated from matchers, then watch for realtime changes.

It is used internally by ContextDB for the matcher indexing.

Installation

$ npm install level-match-map

Example

This module must be used with LevelUP and level-sublevel.

var LevelUp = require('levelup')
var Sublevel = require('level-sublevel')
var MatchMap = require('level-match-map')

var db = Sublevel(LevelUp('/tmp/database-name', {
  encoding: 'json' // need to use json encoding for indexing to work
}))

Now lets specify some matchers and hook into the database.

var matchers = [
  { ref: 'post',
    match: {
      type: 'post',
      id: {$param: 'postId'}
    }
  },
  { ref: 'post_comment',
    match: {
      type: 'comment',
      postId: {$param: 'postId'}
    }
  }
]

var matchDb = MatchMap(db, matchers)

Now if we put objects into our db instance, they will automatically be indexed based on the specified matchers.

var post = {

  id: 'post-1', // used for matching as specified above
  type: 'post', //

  title: 'Typical Blog Post Example',
  body: 'etc...',
  date: Date.now()
}
var comment1 = {
  id: 'comment-1',

  type: 'comment', // used for matching as specified above
  postId: post.id, //

  name: 'Matt McKegg',
  body: 'cool story bro',
  date: Date.now()
}

db.batch([
  {key: post.id, value: post, type: 'put'},
  {key: comment.id, value: comment1, type: 'put'}
])

Time to render our page:


function getPageContext(postId, cb){
  var context = { postId: postId, currentPage: null, comments: [] }
  matchDb.createMatchStream('post', {
    params: context, 
    tail: false
  }).on('data', function(data){

    context.currentPage = data.value

  }).on('end', function(){

    matchDb.createMatchStream('post_comment', {
      params: context, 
      tail: false
    }).on('data', function(data){

      context.comments.push(data.value)

    }).on('end', function(){
      cb(null, context)
    })
  })
}


getPageContext('post-1', function(err, data){
  var html = renderer.render('blog-post', data)
  req.end(html)
})

API

require('level-match-map')(db, matchers)

Specify a sublevel extended db and an array of matchers. An instance of matchDb will be returned.

If the matchers have changed since last time, all objects in db will be re-indexed.

matchDb.lookupMatcher(ref)

Returns the original matcher object as passed in that matches specified ref.

matchDb.createMatcherStream(matcherRef, options)

Returns a level-live-stream emitting a sync event when all current data has been emitted. Call end to stop receiving realtime updates, or specify tail: false in options to cause the stream to automatically close once synced.

Options:

  • tail: defaults to true. Whether to close stream once all current data has been emitted or continue to get live updates.
  • params: params to be used in query in place of $param in matchers
  • queryHandler: instead of specifying params, can also specify a function to handle $query in matchers
  • deletedSince: Objects with the key _deleted: true are not included in the stream by default. Use deletedSince with ms timestamp to access these.

matchDb.forceIndex()

Force the database to re-index all objects. Shouldn't be necessary, as this should happen automatically as needed.

Matchers

Matchers can only be specified at initialization, and from then on only referred to by the name specified under ref. If a database is later initialized with changed matchers, the database will automatically be re-indexed.

The attributes in match are checked using JSON Filter to see if the object should be matched or not. Attributes that are objects with $param or $query as an attribute will instead be added to the index.

Matchers work best when used with something like JSON Context to allow automatic building of contexts that can be streamed to the browser for realtime changes.

npm loves you