UNPKG

pouchdb-find

Version:
132 lines (115 loc) 3.28 kB
'use strict'; var localUtils = require('./utils'); var abstractMapReduce = require('../../abstract-mapreduce'); var parseField = localUtils.parseField; // // One thing about these mappers: // // Per the advice of John-David Dalton (http://youtu.be/NthmeLEhDDM), // what you want to do in this case is optimize for the smallest possible // function, since that's the thing that gets run over and over again. // // This code would be a lot simpler if all the if/elses were inside // the function, but it would also be a lot less performant. // function createDeepMultiMapper(fields, emit) { return function (doc) { var toEmit = []; for (var i = 0, iLen = fields.length; i < iLen; i++) { var parsedField = parseField(fields[i]); var value = doc; for (var j = 0, jLen = parsedField.length; j < jLen; j++) { var key = parsedField[j]; value = value[key]; if (!value) { break; } } toEmit.push(value); } emit(toEmit); }; } function createDeepSingleMapper(field, emit) { var parsedField = parseField(field); return function (doc) { var value = doc; for (var i = 0, len = parsedField.length; i < len; i++) { var key = parsedField[i]; value = value[key]; if (!value) { return; // do nothing } } emit(value); }; } function createShallowSingleMapper(field, emit) { return function (doc) { emit(doc[field]); }; } function createShallowMultiMapper(fields, emit) { return function (doc) { var toEmit = []; for (var i = 0, len = fields.length; i < len; i++) { toEmit.push(doc[fields[i]]); } emit(toEmit); }; } function checkShallow(fields) { for (var i = 0, len = fields.length; i < len; i++) { var field = fields[i]; if (field.indexOf('.') !== -1) { return false; } } return true; } function createMapper(fields, emit) { var isShallow = checkShallow(fields); var isSingle = fields.length === 1; // notice we try to optimize for the most common case, // i.e. single shallow indexes if (isShallow) { if (isSingle) { return createShallowSingleMapper(fields[0], emit); } else { // multi return createShallowMultiMapper(fields, emit); } } else { // deep if (isSingle) { return createDeepSingleMapper(fields[0], emit); } else { // multi return createDeepMultiMapper(fields, emit); } } } function mapper(mapFunDef, emit) { // mapFunDef is a list of fields var fields = Object.keys(mapFunDef.fields); return createMapper(fields, emit); } /* istanbul ignore next */ function reducer(/*reduceFunDef*/) { throw new Error('reduce not supported'); } function ddocValidator(ddoc, viewName) { var view = ddoc.views[viewName]; // This doesn't actually need to be here apparently, but // I feel safer keeping it. /* istanbul ignore if */ if (!view.map || !view.map.fields) { throw new Error('ddoc ' + ddoc._id +' with view ' + viewName + ' doesn\'t have map.fields defined. ' + 'maybe it wasn\'t created by this plugin?'); } } var abstractMapper = abstractMapReduce({ name: 'indexes', mapper: mapper, reducer: reducer, ddocValidator: ddocValidator }); module.exports = abstractMapper;