couchilla is a bundler for packing design documents for CouchDB.
Design documents are a special type of database entry that you can insert to CouchDB, they contain functions such as view and update functions. These functions are executed when requested and create secondary indexes, i.e. MapReduce views.
CouchDB ships with JavaScript and Erlang support, but design functions are language-agnostic. So understandably, the distribution doesn't include a secondary tool to create a design document.
The JavaScript support is based on the Mozilla Spidermonkey engine and it has somewhat strict module dependency rules and other limitations that you need to be aware of while writing your design functions.
couchilla is a tool for conveniently bundling design documents for CouchDB, with CommonJS support. It takes view and filter functions from a directory of JavaScript files and outputs a design document JSON.
Directory structure
Here is an example directory structure of a simple design document:
.
├── filters
│ └── quu.js
├── views
│ ├── foo.map.js
│ └── bar.reduce.js
└── validate_doc_update.js
- Files that contain view functions are located in the
views
folder.- Files with
.map.js
(or only.js
) extensions are transformed into map functions. - Files with
.reduce.js
extensions are transformed into reduce functions.
- Files with
- Files that contain filter functions are located in the
filters
folder.
Examples
Map functions
Emit key/value pairs to store them in a view.
views/foo.map.js
export default doc => emit(doc._id, 42)
Reduce functions
Take sum of mapped values:
views/foo.reduce.js
export default (keys, values, rereduce) => {
if (rereduce) {
return sum(values)
} else {
return values.length
}
}
Filter functions
Filter by field:
filters/foo.js
export default (doc, req) => {
if (doc && doc.title && doc.title.startsWith('C')) {
return true
}
return false
}
Validate document update functions
Log incoming requests and respond with forbidden:
export default (newDoc, oldDoc, userCtx, secObj) => {
log(newDoc)
log(oldDoc)
log(userCtx)
log(secObj)
throw { forbidden: 'not able now!' }
}
Builtin reduce functions
You can opt to use Erlang native functions using the builtin
annotation. For example the sum
function above can be rewritten using _sum
.
views/foo.reduce.js
/* builtin _sum */
During compilation this will be replaced with a call to the builtin _sum
function of CouchDB.
CommonJS
All code should be inside the exported default function, including your require()
calls.
views/gamma.map.js
export default doc => {
const gamma = require('gamma')
emit(doc._id, gamma(doc.value))
}