In this example a key/value pair is emitted for each value in the tags array
of a document with a type of “post”. Note that emit() may be called many
times for a single document, so the same document may be available by several
different keys.

Also keep in mind that each document is sealed to prevent the situation where
one map function changes document state and another receives a modified version.

For efficiency reasons, documents are passed to a group of map functions - each
document is processed by a group of map functions from all views of the related
design document. This means that if you trigger an index update for one view in
the design document, all others will get updated too.

Reduce functions take two required arguments of keys and values lists - the
result of the related map function - and an optional third value which indicates
if rereduce mode is active or not. Rereduce is used for additional reduce
values list, so when it is true there is no information about related keys
(first argument is null).

Note that if the result of a reduce function is longer than the initial
values list then a Query Server error will be raised. However, this behavior
can be disabled by setting reduce_limit config option to false:

[query_server_config]reduce_limit=false

While disabling reduce_limit might be useful for debug proposes, remember
that the main task of reduce functions is to reduce the mapped result, not to
make it bigger. Generally, your reduce function should converge rapidly to a
single value - which could be an array or similar object.

Aproximates the number of distinct keys in a view index using a variant of the
HyperLogLog algorithm. This algorithm enables an efficient, parallelizable
computation of cardinality using fixed memory resources. CouchDB has configured
the underlying data structure to have a relative error of ~2%.

As this reducer ignores the emitted values entirely, an invocation with
group=true will simply return a value of 1 for every distinct key in the
view. In the case of array keys, querying the view with a group_level
specified will return the number of distinct keys that share the common group
prefix in each row. The algorithm is also cognizant of the startkey and
endkey boundaries and will return the number of distinct keys within the
specified key range.

A final note regarding Unicode collation: this reduce function uses the binary
representation of each key in the index directly as input to the HyperLogLog
filter. As such, it will (incorrectly) consider keys that are not byte identical
but that compare equal according to the Unicode collation rules to be distinct
keys, and thus has the potential to overestimate the cardinality of the key
space if a large number of such keys exist.

Computes the following quantities for numeric values associated with each key:
sum, min, max, count, and sumsqr. The behavior of the
_stats function varies depending on the output of the map function. The
simplest case is when the map phase emits a single numeric value for each key.
In this case the _stats function is equivalent to the following JavaScript:

// could be replaced by _statsfunction(keys,values,rereduce){if(rereduce){return{'sum':values.reduce(function(a,b){returna+b.sum},0),'min':values.reduce(function(a,b){returnMath.min(a,b.min)},Infinity),'max':values.reduce(function(a,b){returnMath.max(a,b.max)},-Infinity),'count':values.reduce(function(a,b){returna+b.count},0),'sumsqr':values.reduce(function(a,b){returna+b.sumsqr},0)}}else{return{'sum':sum(values),'min':Math.min.apply(null,values),'max':Math.max.apply(null,values),'count':values.length,'sumsqr':(function(){varsumsqr=0;values.forEach(function(value){sumsqr+=value*value;});returnsumsqr;})(),}}}

The _stats function will also work with “pre-aggregated” values from a map
phase. A map function that emits an object containing sum, min, max,
count, and sumsqr keys and numeric values for each can use the
_stats function to combine these results with the data from other documents.
The emitted object may contain other keys (these are ignored by the reducer),
and it is also possible to mix raw numeric values and pre-aggregated objects
in a single view and obtain the correct aggregated statistics.

Finally, _stats can operate on key-value pairs where each value is an array
comprised of numbers or pre-aggregated objects. In this case every value
emitted from the map function must be an array, and the arrays must all be the
same length, as _stats will compute the statistical quantities above
independently for each element in the array. Users who want to compute
statistics on multiple values from a single document should either emit each
value into the index separately, or compute the statistics for the set of values
using the JavaScript example above and emit a pre-aggregated object.

In its simplest variation, _sum sums the numeric values associated with each
key, as in the following JavaScript:

// could be replaced by _sumfunction(keys,values){returnsum(values);}

As with _stats, the _sum function offers a number of extended
capabilities. The _sum function requires that map values be numbers, arrays
of numbers, or objects. When presented with array output from a map function,
_sum will compute the sum for every element of the array. A bare numeric
value will be treated as an array with a single element, and arrays with fewer
elements will be treated as if they contained zeroes for every additional
element in the longest emitted array. As an example, consider the following map
output:

This is in contrast to the behavior of the _stats function which requires
that all emitted values be arrays of identical length if any array is emitted.

It is also possible to have _sum recursively descend through an emitted
object and compute the sums for every field in the object. Objects cannot be
mixed with other data structures. Objects can be arbitrarily nested, provided
that the values for all fields are themselves numbers, arrays of numbers, or
objects.

Note

Why don’t reduce functions support CommonJS modules?

While map functions have limited access to stored modules through
require(), there is no such feature for reduce functions.
The reason lies deep inside the way map and reduce
functions are processed by the Query Server. Let’s take a look at map
functions first:

CouchDB sends all map functions in a processed design document to the
Query Server.

the Query Server handles them one by one, compiles and puts them onto an
internal stack.

after all map functions have been processed, CouchDB will send the
remaining documents for indexing, one by one.

the Query Server receives the document object and applies it to every
function from the stack. The emitted results are then joined into a
single array and sent back to CouchDB.

Now let’s see how reduce functions are handled:

CouchDB sends as a single command the list of available reduce
functions with the result list of key-value pairs that were previously
returned from the map functions.

the Query Server compiles the reduce functions and applies them to the
key-value lists. The reduced result is sent back to CouchDB.

As you may note, reduce functions are applied in a single shot to the map
results while map functions are applied to documents one by one. This
means that it’s possible for map functions to precompile CommonJS
libraries and use them during the entire view processing, but for reduce
functions they would be compiled again and again for each view result
reduction, which would lead to performance degradation.

Show functions are used to represent documents in various formats, commonly as
HTML pages with nice formatting. They can also be used to run server-side
functions without requiring a pre-existing document.

Templates and styles could obviously be used to present data in a nicer fashion,
but this is an excellent starting point. Note that you may also use
registerType() and provides() functions in a similar way as for
Show Functions! However, note that provides() expects the return value to
be a string when used inside a list function, so you’ll need to use
start() to set any custom headers and stringify your JSON before
returning it.

Two-element array: the first element is the (updated or new)
document, which is committed to the database. If the first element
is null no document will be committed to the database.
If you are updating an existing document, it should already have an
_id set, and if you are creating a new document, make sure to set its
_id to something, either generated based on the input or the
req.uuid provided. The second element is the response that will
be sent back to the caller.

Update handlers are functions that clients can request to invoke server-side
logic that will create or update a document. This feature allows a range of use
cases such as providing a server-side last modified timestamp, updating
individual fields in a document without first getting the latest revision, etc.

When the request to an update handler includes a document ID in the URL, the
server will provide the function with the most recent version of that document.
You can provide any other values needed by the update handler function via the
POST/PUT entity body or query string parameters of the request.

Note that the value of last_seq is 10-.., but we received only two records.
Seems like any other changes were for documents that haven’t passed our filter.

We probably need to filter the changes feed of our mailbox by more than a single
status value. We’re also interested in statuses like “spam” to update
spam-filter heuristic rules, “outgoing” to let a mail daemon actually send
mails, and so on. Creating a lot of similar functions that actually do similar
work isn’t good idea - so we need a dynamic filter.

You may have noticed that filter functions take a second argument named
request. This allows the creation of dynamic filters
based on query parameters, user context and more.

The dynamic version of our filter looks like this:

function(doc,req){// we need only `mail` documentsif(doc.type!='mail'){returnfalse;}// we're interested only in requested statusif(doc.status!=req.query.status){returnfalse;}returntrue;// passed!}

and now we have passed the status query parameter in the request to let our
filter match only the required documents:

GET /somedatabase/_changes?filter=mailbox/by_status&status=new HTTP/1.1

View filters are the same as classic filters above, with one small difference:
they use the map instead of the filter function of a view, to filter the
changes feed. Each time a key-value pair is emitted from the map function, a
change is returned. This allows avoiding filter functions that mostly do the
same work as views.

To use them just pass filter=_view and view=designdoc/viewname as request
parameters to the changes feed:

GET /somedatabase/_changes?filter=_view&view=dname/viewname HTTP/1.1

Note

Since view filters use map functions as filters, they can’t show any
dynamic behavior since request object is not
available.

A design document may contain a function named validate_doc_update
which can be used to prevent invalid or unauthorized document update requests
from being stored. The function is passed the new document from the update
request, the current document stored in the database, a User Context Object
containing information about the user writing the document (if present), and
a Security Object with lists of database security roles.

Validation functions typically examine the structure of the new document to
ensure that required fields are present and to verify that the requesting user
should be allowed to make changes to the document properties. For example,
an application may require that a user must be authenticated in order to create
a new document or that specific document fields be present when a document
is updated. The validation function can abort the pending document write
by throwing one of two error objects:

// user is not authorized to make the change but may re-authenticatethrow({unauthorized:'Error message here.'});// change is not allowedthrow({forbidden:'Error message here.'});

Document validation is optional, and each design document in the database may
have at most one validation function. When a write request is received for
a given database, the validation function in each design document in that
database is called in an unspecified order. If any of the validation functions
throw an error, the write will not succeed.

Example: The _design/_auth ddoc from _users database uses a validation
function to ensure that documents contain some required fields and are only
modified by a user with the _admin role:

function(newDoc,oldDoc,userCtx,secObj){if(newDoc._deleted===true){// allow deletes by admins and matching users// without checking the other fieldsif((userCtx.roles.indexOf('_admin')!==-1)||(userCtx.name==oldDoc.name)){return;}else{throw({forbidden:'Only admins may delete other user docs.'});}}if((oldDoc&&oldDoc.type!=='user')||newDoc.type!=='user'){throw({forbidden:'doc.type must be user'});}// we only allow user docs for nowif(!newDoc.name){throw({forbidden:'doc.name is required'});}if(!newDoc.roles){throw({forbidden:'doc.roles must exist'});}if(!isArray(newDoc.roles)){throw({forbidden:'doc.roles must be an array'});}if(newDoc._id!==('org.couchdb.user:'+newDoc.name)){throw({forbidden:'Doc ID must be of the form org.couchdb.user:name'});}if(oldDoc){// validate all updatesif(oldDoc.name!==newDoc.name){throw({forbidden:'Usernames can not be changed.'});}}if(newDoc.password_sha&&!newDoc.salt){throw({forbidden:'Users with password_sha must have a salt.'+'See /_utils/script/couch.js for example code.'});}varis_server_or_database_admin=function(userCtx,secObj){// see if the user is a server adminif(userCtx.roles.indexOf('_admin')!==-1){returntrue;// a server admin}// see if the user a database admin specified by nameif(secObj&&secObj.admins&&secObj.admins.names){if(secObj.admins.names.indexOf(userCtx.name)!==-1){returntrue;// database admin}}// see if the user a database admin specified by roleif(secObj&&secObj.admins&&secObj.admins.roles){vardb_roles=secObj.admins.roles;for(varidx=0;idx<userCtx.roles.length;idx++){varuser_role=userCtx.roles[idx];if(db_roles.indexOf(user_role)!==-1){returntrue;// role matches!}}}returnfalse;// default to no admin}if(!is_server_or_database_admin(userCtx,secObj)){if(oldDoc){// validate non-admin updatesif(userCtx.name!==newDoc.name){throw({forbidden:'You may only update your own user document.'});}// validate role updatesvaroldRoles=oldDoc.roles.sort();varnewRoles=newDoc.roles.sort();if(oldRoles.length!==newRoles.length){throw({forbidden:'Only _admin may edit roles'});}for(vari=0;i<oldRoles.length;i++){if(oldRoles[i]!==newRoles[i]){throw({forbidden:'Only _admin may edit roles'});}}}elseif(newDoc.roles.length>0){throw({forbidden:'Only _admin may set roles'});}}// no system roles in users dbfor(vari=0;i<newDoc.roles.length;i++){if(newDoc.roles[i][0]==='_'){throw({forbidden:'No system roles (starting with underscore) in users db.'});}}// no system names as namesif(newDoc.name[0]==='_'){throw({forbidden:'Username may not start with underscore.'});}varbadUserNameChars=[':'];for(vari=0;i<badUserNameChars.length;i++){if(newDoc.name.indexOf(badUserNameChars[i])>=0){throw({forbidden:'Character `'+badUserNameChars[i]+'` is not allowed in usernames.'});}}}

Note

The return statement is used only for function, it has no impact on
the validation process.