UNPKG

hyperlog-join

Version:
140 lines (123 loc) 3.39 kB
var hindex = require('hyperlog-index') var sub = require('subleveldown') var through = require('through2') var readonly = require('read-only-stream') var EventEmitter = require('events').EventEmitter var inherits = require('inherits') var concat = require('concat-stream') module.exports = Join inherits(Join, EventEmitter) function Join (opts) { if (!(this instanceof Join)) return new Join(opts) var self = this EventEmitter.call(self) self.map = opts.map self.log = opts.log self.idb = sub(opts.db, 'i') self.xdb = sub(opts.db, 'x', { valueEncoding: opts.valueEncoding || opts.log.valueEncoding || 'json' }) self.dex = hindex({ log: self.log, db: self.idb, map: mapfn }) function mapfn (row, next) { if (row.value === undefined) return next() self.map(row, function (err, res) { if (err) return next(err) if (res === undefined || (res.key === undefined && !Array.isArray(res))) { return next() } var batch = ops(Array.isArray(res) ? res : [res]) self.xdb.batch(batch, next) }) function ops (rows) { var batch = rows.map(map) var rels = {} rows.forEach(function (row) { rels[row.key] = true }) Object.keys(rels).forEach(function (key) { batch.push({ type: 'put', key: 'r!' + key, value: 0 }) }) return batch } function map (r) { if (r.type === 'del') { return { type: 'del', key: 'h!' + Buffer(r.key).toString('hex') + '!' + r.rowKey } } else { return { type: 'put', key: 'h!' + Buffer(r.key).toString('hex') + '!' + row.key, value: r.value } } } } self.dex.on('error', function (err) { self.emit('error', err) }) } Join.prototype.list = function (key, opts, cb) { var self = this if (typeof opts === 'function') { cb = opts opts = {} } if (!opts) opts = {} var rows = cb ? [] : null var stream = through.obj(write, end) var hkey = 'h!' + Buffer(key).toString('hex') self.dex.ready(function () { var r = self.xdb.createReadStream({ gt: hkey + '!', lt: hkey + '!~' }) r.on('error', stream.emit.bind(stream, 'error')) r.pipe(stream) if (cb) { r.once('error', cb) var c = concat({encoding:'object'}, cb.bind(null, null)) stream.pipe(c) } }) return readonly(stream) function write (row, enc, next) { var rec = { key: row.key.replace(/^h![^!]+!/,''), value: row.value } if (rows) rows.push(rec) next(null, rec) } function end (next) { next() } } Join.prototype.relations = function (opts) { var self = this if (!opts) opts = {} var stream = through.obj(write, end) self.dex.ready(function () { var xopts = {} if (opts.gt) xopts.gt = 'r!' + opts.gt else if (opts.gte) xopts.gte = 'r!' + opts.gte else xopts.gt = 'r!' if (opts.lt) xopts.lt = 'r!' + opts.lt else if (opts.lte) xopts.lte = 'r!' + opts.lte else xopts.lt = 'r!~' if (opts.limit !== undefined) xopts.limit = opts.limit var r = self.xdb.createReadStream(xopts) r.on('error', stream.emit.bind(stream, 'error')) r.pipe(stream) }) return readonly(stream) function write (row, enc, next) { next(null, row.key.replace(/^r!/,'')) } function end (next) { next() } }