Nicotine Powered Man


    2.0.0 • Public • Published


    Automatic secondary indexing for leveldb and subleveldown.

    npm install level-auto-index

    level badge npm Build Status dependencies Status devDependencies Status


    var level = require('level')
    var AutoIndex = require('level-auto-index')
    var sub = require('subleveldown')
    var keyReducer = AutoIndex.keyReducer
    var db = level()
    var posts = sub(db, 'posts', {valueEncoding: 'json'})
    var idx = {
      title: sub(db, 'title'),
      length: sub(db, 'length'),
      tag: sub(db, 'tag')
    // add a title index
    posts.byTitle = AutoIndex(posts, idx.title, keyReducer('title'))
    // add a length index
    // append the for unique indexes with possibly overlapping values
    posts.byLength = AutoIndex(posts, idx.length, function (post) {
      return post.body.length + '!' +
    // Create multiple index keys on an index
    posts.byTag = AutoIndex(posts, idx.tag, function (post) {
        if (!post || !post.tags || !Array.isArray(post.tags)) return
        return (tag) {
          return [tag,].join('!')
      }, { multi: true })
    posts.put('1337', {
      id: '1337',
      title: 'a title',
      body: 'lorem ipsum',
      tags: [ 'foo', 'bar', 'baz' ]
    }, function (err) {
      if (err) throw err
      posts.byTitle.get('a title', function (err, post) {
        if (err) throw err
        console.log('get', post)
        // => get: { id: '1337', title: 'a title', body: 'lorem ipsum' }
        posts.del('1337', function (err) {
          if (err) throw err
          posts.byTitle.get('a title', function (err) {
            // => NotFoundError
        start: 10,
        end: 20
      }).on('data', console.log.bind(console, 'read'))
      // => read { key: '1337', value: { id: '1337', title: 'a title', body: 'lorem ipsum' } }
        start: 10,
        end: 20
      }).on('data', console.log.bind(console, 'key'))
      // => key 1337
        start: 10,
        end: 20
      }).on('data', console.log.bind(console, 'value'))
      // => value { id: '1337', title: 'a title', body: 'lorem ipsum' }


    AutoIndex(db, idb, reduce, opts)

    Automatically index a db level into the idb level using a reduce function that creates the index key. The db and idb levels should be in isolated key namespaces, either by being two different levels or mafintosh/subleveldown partitions. The db hook is mutated by hypermodules/level-hookdown to set up the prehooks used for indexing. Only db keys are stored as values to save space and reduce data redundancy.

    Secondary returns an AutoIndex level that helps prune old index values, and automatically looks up source documents from db as you access keys on the AutoIndex level.

    The reduce functions get the value of the put or batch operations. Make sure that this value has everything you need to create your index keys.

    function reducer (value) {
      var idxKey = + '!' +
      return idxKey

    Available opts:

      multi: false // Reducer returns an array of keys to associate with the primary key

    Multi-key index's are for when you you want to write multiple index entries into an index. This is useful for 'tag' fields, where a document may have n tags per document, and you would like to index documents by 'tag'. When creating a multi-key index, your reducer must return an array of keys to index by.

    AutoIndex#get(key, opts, cb)

    Get the value that has been indexed with key.


    Create a readable stream that has indexes as keys and indexed data as values.


    A level manifest that you can pass to multilevel.


    A shortcut reducer for simplistic key indexing. You might need more than this.

    function keyReducer (reducerString) {
      function keyRdc (value) {
        return value[reducerString]
      return keyRdc

    For a higher level api for creating secondary indexes see hypermodules/level-idx.


    A shortcut reducer for simplistic multi-key indexing. You might need more than this.

    function multiKeyReducer (multiFieldName, primaryKeyFieldName) {
      return function multiKeyrdc (document) {
        if (!document || !document[multiFieldName] || !Array.isArray(document[multiFieldName])) return
        return document[multiFieldName].map(function (tag) {
          return [tag, document[primaryKeyFieldName]].join('!')


    The level instance that we are indexing.


    The level instance that we are using for the index.

    See Also

    This module is a variant of

    but aimed at decoupling the index storage fromt the indexd db and also being compatable with subleveldown. It came out of the work trying to make level-secondary compatable with subleveldown and level-sublevel. That work lives here:


    npm i level-auto-index

    DownloadsWeekly Downloads






    Unpacked Size

    26.3 kB

    Total Files


    Last publish


    • bret