couchdb-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From kxe...@apache.org
Subject [08/14] Documentation was moved to couchdb-documentation repository
Date Thu, 16 Oct 2014 09:09:20 GMT
http://git-wip-us.apache.org/repos/asf/couchdb/blob/cdac7299/share/doc/src/couchapp/ddocs.rst
----------------------------------------------------------------------
diff --git a/share/doc/src/couchapp/ddocs.rst b/share/doc/src/couchapp/ddocs.rst
deleted file mode 100644
index 4f4664a..0000000
--- a/share/doc/src/couchapp/ddocs.rst
+++ /dev/null
@@ -1,768 +0,0 @@
-.. Licensed under the Apache License, Version 2.0 (the "License"); you may not
-.. use this file except in compliance with the License. You may obtain a copy of
-.. the License at
-..
-..   http://www.apache.org/licenses/LICENSE-2.0
-..
-.. Unless required by applicable law or agreed to in writing, software
-.. distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-.. WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-.. License for the specific language governing permissions and limitations under
-.. the License.
-
-.. default-domain:: js
-
-.. _ddocs:
-
-================
-Design Functions
-================
-
-In this section we'll show how to write design documents, using the built-in
-:ref:`JavaScript Query Server <query-server/js>`.
-
-But before we start to write our first function, let's take a look at the list
-of common objects that will be used during our code journey - we'll be using
-them extensively within each function:
-
-- :ref:`Database information object <dbinfo_object>`
-- :ref:`Request object <request_object>`
-- :ref:`Response object <response_object>`
-- :ref:`UserCtx object <userctx_object>`
-- :ref:`Database Security object <security_object>`
-- :ref:`Guide to JavaScript Query Server <query-server/js>`
-
-.. _viewfun:
-
-View functions
-==============
-
-Views are the primary tool used for querying and reporting on CouchDB databases.
-
-.. _mapfun:
-
-Map functions
--------------
-
-.. function:: mapfun(doc)
-
-   :param doc: Processed document object.
-
-Map functions accept a single document as the argument and (optionally) :func:`emit`
-key/value pairs that are stored in a view.
-
-.. code-block:: javascript
-
-    function (doc) {
-      if (doc.type === 'post' && doc.tags && Array.isArray(doc.tags)) {
-        doc.tags.forEach(function (tag) {
-          emit(tag.toLowerCase(), 1);
-        });
-      }
-    }
-
-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 :func:`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 situation when one
-map function changes document state and the other one received a modified
-version.
-
-For efficiency reasons, documents are passed to a group of map functions -
-each document is processed by group of map functions from all views of
-related design document. This means that if you trigger index update for one
-view in ddoc, all others will get updated too.
-
-Since `1.1.0` release `map` function supports
-:ref:`CommonJS <commonjs>` modules and access to :func:`require` function.
-
-.. _reducefun:
-
-Reduce and rereduce functions
------------------------------
-
-.. function:: redfun(keys, values[, rereduce])
-
-   :param keys: Array of pairs docid-key for related map function result.
-                Always ``null`` if rereduce is running (has ``true`` value).
-   :param values: Array of map function result values.
-   :param rereduce: Boolean sign of rereduce run.
-
-   :return: Reduces `values`
-
-Reduce functions takes two required arguments of keys and values lists - the
-result of the related map function - and optional third one which indicates if
-`rereduce` mode is active or not. `Rereduce` is using for additional reduce
-values list, so when it is ``true`` there is no information about related `keys`
-(first argument is ``null``).
-
-Note, that if produced result by `reduce` function is longer than initial
-values list then a Query Server error will be raised. However, this behavior
-could be disabled by setting ``reduce_limit`` config option to ``false``:
-
-.. code-block:: ini
-
-   [query_server_config]
-   reduce_limit = false
-
-While disabling ``reduce_limit`` might be useful for debug proposes, remember,
-that main task of reduce functions is to *reduce* mapped result, not to make it
-even bigger. Generally, your reduce function should converge rapidly to a single
-value - which could be an array or similar object.
-
-
-.. _reducefun/builtin:
-
-Builtin reduce functions
-^^^^^^^^^^^^^^^^^^^^^^^^
-
-Additionally, CouchDB has three built-in reduce functions. These are implemented
-in Erlang and runs inside CouchDB, so they are much faster than the equivalent
-JavaScript functions: ``_sum``, ``_count`` and ``_stats``. Their equivalents in
-JavaScript below:
-
-.. code-block:: javascript
-
-    // could be replaced by _sum
-    function(keys, values) {
-      return sum(values);
-    }
-
-    // could be replaced by _count
-    function(keys, values, rereduce) {
-      if (rereduce) {
-        return sum(values);
-      } else {
-        return values.length;
-      }
-    }
-
-    // could be replaced by _stats
-    function(keys, values, rereduce) {
-      if (rereduce) {
-        return {
-          'sum': values.reduce(function(a, b) { return a + b.sum }, 0),
-          'min': values.reduce(function(a, b) { return Math.min(a, b.min) }, Infinity),
-          'max': values.reduce(function(a, b) { return Math.max(a, b.max) }, -Infinity),
-          'count': values.reduce(function(a, b) { return a + b.count }, 0),
-          'sumsqr': values.reduce(function(a, b) { return a + 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() {
-            var sumsqr = 0;
-
-            values.forEach(function (value) {
-              sumsqr += value * value;
-            });
-
-            return sumsqr;
-          })(),
-        }
-      }
-    }
-
-.. note:: **Why don't reduce functions support CommonJS modules?**
-
-   While `map` functions have limited access to stored modules through
-   :func:`require` function there is no such feature for `reduce` functions.
-   The reason lies deep inside in mechanism how `map` and `reduce` functions
-   are processed by Query Server. Let's take a look on `map` functions first:
-
-   #. CouchDB sends all `map` functions for processed design document to
-      Query Server.
-   #. Query Server handles them one by one, compiles and puts them onto an
-      internal stack.
-   #. After all `map` functions had been processed, CouchDB will send the
-      remaining documents to index 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 single command* list of available `reduce` functions
-      with result list of key-value pairs that was previously received as
-      result of `map` functions work.
-   #. Query Server compiles reduce functions and applies them to key-value
-      lists. Reduced result sends back to CouchDB.
-
-   As you may note, `reduce` functions been applied in single shot while
-   `map` ones are applied in an iterative way per each document. 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 it will be
-   compiled again and again for each view result reduction, which will lead to
-   performance degradation (`reduce` function are already does hard work to make
-   large result smaller).
-
-
-.. _showfun:
-
-Show functions
-==============
-
-.. function:: showfun(doc, req)
-
-   :param doc: Processed document, may be omitted.
-   :param req: :ref:`Request object <request_object>`.
-
-   :return: :ref:`Response object <response_object>`
-   :rtype: object or string
-
-Show functions are used to represent documents in various formats, commonly as
-HTML page with nicer formatting. They can also be used to run server-side functions
-without requiring a pre-existing document.
-
-Basic example of show function could be:
-
-.. code-block:: javascript
-
-    function(doc, req){
-      if (doc) {
-        return "Hello from " + doc._id + "!";
-      } else {
-        return "Hello, world!";
-      }
-    }
-
-Also, there is more simple way to return json encoded data:
-
-.. code-block:: javascript
-
-    function(doc, req){
-      return {
-        'json': {
-          'id': doc['_id'],
-          'rev': doc['_rev']
-        }
-      }
-    }
-
-
-and even files (this one is CouchDB logo):
-
-.. code-block:: javascript
-
-    function(doc, req){
-      return {
-        'headers': {
-          'Content-Type' : 'image/png',
-        },
-        'base64': ''.concat(
-          'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAsV',
-          'BMVEUAAAD////////////////////////5ur3rEBn////////////////wDBL/',
-          'AADuBAe9EB3IEBz/7+//X1/qBQn2AgP/f3/ilpzsDxfpChDtDhXeCA76AQH/v7',
-          '/84eLyWV/uc3bJPEf/Dw/uw8bRWmP1h4zxSlD6YGHuQ0f6g4XyQkXvCA36MDH6',
-          'wMH/z8/yAwX64ODeh47BHiv/Ly/20dLQLTj98PDXWmP/Pz//39/wGyJ7Iy9JAA',
-          'AADHRSTlMAbw8vf08/bz+Pv19jK/W3AAAAg0lEQVR4Xp3LRQ4DQRBD0QqTm4Y5',
-          'zMxw/4OleiJlHeUtv2X6RbNO1Uqj9g0RMCuQO0vBIg4vMFeOpCWIWmDOw82fZx',
-          'vaND1c8OG4vrdOqD8YwgpDYDxRgkSm5rwu0nQVBJuMg++pLXZyr5jnc1BaH4GT',
-          'LvEliY253nA3pVhQqdPt0f/erJkMGMB8xucAAAAASUVORK5CYII=')
-      }
-    }
-
-But what if you need to represent data in different formats via a single function?
-Functions :func:`registerType` and :func:`provides` are your the best friends in
-that question:
-
-.. code-block:: javascript
-
-    function(doc, req){
-      provides('json', function(){
-        return {'json': doc}
-      });
-      provides('html', function(){
-        return '<pre>' + toJSON(doc) + '</pre>'
-      })
-      provides('xml', function(){
-        return {
-          'headers': {'Content-Type': 'application/xml'},
-          'body' : ''.concat(
-            '<?xml version="1.0" encoding="utf-8"?>\n',
-            '<doc>',
-            (function(){
-              escape = function(s){
-                return s.replace(/&quot;/g, '"')
-                        .replace(/&gt;/g, '>')
-                        .replace(/&lt;/g, '<')
-                        .replace(/&amp;/g, '&');
-              };
-              var content = '';
-              for(var key in doc){
-                if(!doc.hasOwnProperty(key)) continue;
-                var value = escape(toJSON(doc[key]));
-                var key = escape(key);
-                content += ''.concat(
-                  '<' + key + '>',
-                  value
-                  '</' + key + '>'
-                )
-              }
-              return content;
-            })(),
-            '</doc>'
-          )
-        }
-      })
-      registerType('text-json', 'text/json')
-      provides('text-json', function(){
-        return toJSON(doc);
-      })
-    }
-
-This function may return `html`, `json` , `xml` or our custom `text json` format
-representation of same document object with same processing rules. Probably,
-the `xml` provider in our function needs more care to handle nested objects
-correctly, and keys with invalid characters, but you've got the idea!
-
-.. seealso::
-
-   CouchDB Wiki:
-    - `Showing Documents <http://wiki.apache.org/couchdb/Formatting_with_Show_and_List#Showing_Documents>`_
-
-   CouchDB Guide:
-     - `Show Functions <http://guide.couchdb.org/editions/1/en/show.html>`_
-
-
-.. _listfun:
-
-List functions
-==============
-
-.. function:: listfun(head, req)
-
-   :param head: :ref:`view_head_info_object`
-   :param req: :ref:`Request object <request_object>`.
-
-   :return: Last chunk.
-   :rtype: string
-
-While :ref:`showfun` are used to customize document presentation, :ref:`listfun`
-are used for same purpose, but against :ref:`viewfun` results.
-
-The next list function formats view and represents it as a very simple HTML page:
-
-.. code-block:: javascript
-
-    function(head, req){
-      start({
-        'headers': {
-          'Content-Type': 'text/html'
-        }
-      });
-      send('<html><body><table>');
-      send('<tr><th>ID</th><th>Key</th><th>Value</th></tr>')
-      while(row = getRow()){
-        send(''.concat(
-          '<tr>',
-          '<td>' + toJSON(row.id) + '</td>',
-          '<td>' + toJSON(row.key) + '</td>',
-          '<td>' + toJSON(row.value) + '</td>',
-          '</tr>'
-        ));
-      }
-      send('</table></body></html>');
-    }
-
-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 :func:`registerType` and :func:`provides` functions in the same
-way as for :ref:`showfun`!
-
-.. seealso::
-
-   CouchDB Wiki:
-    - `Listing Views with CouchDB 0.10 and later <http://wiki.apache.org/couchdb/Formatting_with_Show_and_List#Listing_Views_with_CouchDB_0.10_and_later>`_
-
-   CouchDB Guide:
-    - `Transforming Views with List Functions <http://guide.couchdb.org/draft/transforming.html>`_
-
-
-.. _updatefun:
-
-Update functions
-================
-
-.. function:: updatefun(doc, req)
-
-   :param doc: Update function target document.
-   :param req: :ref:`request_object`
-
-   :returns: 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, 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.
-
-The basic example that demonstrates all use-cases of update handlers below:
-
-.. code-block:: javascript
-
-    function(doc, req){
-        if (!doc){
-            if ('id' in req && req['id']){
-                // create new document
-                return [{'_id': req['id']}, 'New World']
-            }
-            // change nothing in database
-            return [null, 'Empty World']
-        }
-        doc['world'] = 'hello';
-        doc['edited_by'] = req['userCtx']['name']
-        return [doc, 'Edited World!']
-    }
-
-.. seealso::
-
-   CouchDB Wiki:
-    - `Document Update Handlers <http://wiki.apache.org/couchdb/Document_Update_Handlers>`_
-
-
-.. _filterfun:
-
-Filter functions
-================
-
-.. function:: filterfun(doc, req)
-
-   :param doc: Processed document object.
-   :param req: :ref:`request_object`
-   :return: Boolean value: ``true`` means that `doc` passes the filter rules,
-            ``false`` means that it does not.
-
-Filter functions mostly act like :ref:`showfun` and :ref:`listfun`: they
-format, or *filter* the :ref:`changes feed<changes>`.
-
-Classic filters
----------------
-
-By default the changes feed emits all database documents changes. But if you're
-waiting for some special changes, processing all documents is inefficient.
-
-Filters are special design document functions that allow the changes feed to emit
-only specific documents that pass filter rules.
-
-Let's assume that our database is a mailbox and we need to handle only new mail
-events (documents with status `new`). Our filter function will look like this:
-
-.. code-block:: javascript
-
-  function(doc, req){
-    // we need only `mail` documents
-    if (doc.type != 'mail'){
-      return false;
-    }
-    // we're interested only in `new` ones
-    if (doc.status != 'new'){
-      return false;
-    }
-    return true; // passed!
-  }
- 
-Filter functions must return ``true`` if a document passed all defined
-rules. Now, if you apply this function to the changes feed it will emit only changes
-about "new mails"::
-
-    GET /somedatabase/_changes?filter=mailbox/new_mail HTTP/1.1
-
-.. code-block:: javascript
-
-    {"results":[
-    {"seq":1,"id":"df8eca9da37dade42ee4d7aa3401f1dd","changes":[{"rev":"1-c2e0085a21d34fa1cecb6dc26a4ae657"}]},
-    {"seq":7,"id":"df8eca9da37dade42ee4d7aa34024714","changes":[{"rev":"1-29d748a6e87b43db967fe338bcb08d74"}]},
-    ],
-    "last_seq":27}
-
-Note that the value of ``last_seq`` is 27, but we'd 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
-:ref:`request <request_object>` - it allows creating dynamic filters
-based on query parameters, :ref:`user context <userctx_object>` and more.
-
-The dynamic version of our filter looks like this:
-
-.. code-block:: javascript
-
-  function(doc, req){
-    // we need only `mail` documents
-    if (doc.type != 'mail'){
-      return false;
-    }
-    // we're interested only in requested status
-    if (doc.status != req.query.status){
-      return false;
-    }
-    return true; // passed!
-  }
-
-and now we have passed the `status` query parameter in request to let our filter match
-only required documents::
-
-    GET /somedatabase/_changes?filter=mailbox/by_status&status=new HTTP/1.1
-
-.. code-block:: javascript
-
-    {"results":[
-    {"seq":1,"id":"df8eca9da37dade42ee4d7aa3401f1dd","changes":[{"rev":"1-c2e0085a21d34fa1cecb6dc26a4ae657"}]},
-    {"seq":7,"id":"df8eca9da37dade42ee4d7aa34024714","changes":[{"rev":"1-29d748a6e87b43db967fe338bcb08d74"}]},
-    ],
-    "last_seq":27}
-
-and we can easily change filter behavior with::
-
-    GET /somedatabase/_changes?filter=mailbox/by_status&status=spam HTTP/1.1
-
-.. code-block:: javascript
-
-    {"results":[
-    {"seq":11,"id":"8960e91220798fc9f9d29d24ed612e0d","changes":[{"rev":"3-cc6ff71af716ddc2ba114967025c0ee0"}]},
-    ],
-    "last_seq":27}
-
-
-Combining filters with a `continuous` feed allows creating powerful event-driven
-systems.
-
-.. _viewfilter:
-
-View filters
-------------
-
-View filters are the same as above, with one small difference: they use
-views `map` function instead to `filter` one to process the changes feed. Each
-time when a key-value pair could be emitted, a change is returned. This allows
-to avoid creating filter functions that are mostly does same works as views.
-
-To use them just specify `_view` value for ``filter`` parameter and
-`designdoc/viewname` for ``view`` one::
-
-    GET /somedatabase/_changes?filter=_view&view=dname/viewname  HTTP/1.1
-
-.. note::
-
-   Since view filters uses `map` functions as filters, they can't show any
-   dynamic behavior since :ref:`request object<request_object>` is not
-   available.
-
-.. seealso::
-
-   CouchDB Guide:
-    - `Guide to filter change notification <http://guide.couchdb.org/draft/notifications.html#filters>`_
-
-   CouchDB Wiki:
-    - `Filtered replication <http://wiki.apache.org/couchdb/Replication#Filtered_Replication>`_
-
-
-.. _vdufun:
-
-Validate document update functions
-==================================
-
-.. function:: validatefun(newDoc, oldDoc, userCtx, secObj)
-
-   :param newDoc: New version of document that will be stored.
-   :param oldDoc: Previous version of document that is already stored.
-   :param userCtx: :ref:`userctx_object`
-   :param secObj: :ref:`security_object`
-
-   :throws: ``forbidden`` error to gracefully prevent document storing.
-   :throws: ``unauthorized`` error to prevent storage and allow the user to
-            re-auth.
-
-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 :ref:`userctx_object`
-containing information about the user writing the document (if present), and
-a :ref:`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:
-
-.. code-block:: javascript
-
-  // user is not authorized to make the change but may re-authenticate
-  throw({ unauthorized: 'Error message here.' });
-  
-  // change is not allowed
-  throw({ 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:
-
-.. code-block:: javascript
-
-    function(newDoc, oldDoc, userCtx, secObj) {
-        if (newDoc._deleted === true) {
-            // allow deletes by admins and matching users
-            // without checking the other fields
-            if ((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 now
-
-        if (!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 updates
-            if (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.'
-            });
-        }
-
-        var is_server_or_database_admin = function(userCtx, secObj) {
-            // see if the user is a server admin
-            if(userCtx.roles.indexOf('_admin') !== -1) {
-                return true; // a server admin
-            }
-
-            // see if the user a database admin specified by name
-            if(secObj && secObj.admins && secObj.admins.names) {
-                if(secObj.admins.names.indexOf(userCtx.name) !== -1) {
-                    return true; // database admin
-                }
-            }
-
-            // see if the user a database admin specified by role
-            if(secObj && secObj.admins && secObj.admins.roles) {
-                var db_roles = secObj.admins.roles;
-                for(var idx = 0; idx < userCtx.roles.length; idx++) {
-                    var user_role = userCtx.roles[idx];
-                    if(db_roles.indexOf(user_role) !== -1) {
-                        return true; // role matches!
-                    }
-                }
-            }
-
-            return false; // default to no admin
-        }
-
-        if (!is_server_or_database_admin(userCtx, secObj)) {
-            if (oldDoc) { // validate non-admin updates
-                if (userCtx.name !== newDoc.name) {
-                    throw({
-                        forbidden: 'You may only update your own user document.'
-                    });
-                }
-                // validate role updates
-                var oldRoles = oldDoc.roles.sort();
-                var newRoles = newDoc.roles.sort();
-
-                if (oldRoles.length !== newRoles.length) {
-                    throw({forbidden: 'Only _admin may edit roles'});
-                }
-
-                for (var i = 0; i < oldRoles.length; i++) {
-                    if (oldRoles[i] !== newRoles[i]) {
-                        throw({forbidden: 'Only _admin may edit roles'});
-                    }
-                }
-            } else if (newDoc.roles.length > 0) {
-                throw({forbidden: 'Only _admin may set roles'});
-            }
-        }
-
-        // no system roles in users db
-        for (var i = 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 names
-        if (newDoc.name[0] === '_') {
-            throw({forbidden: 'Username may not start with underscore.'});
-        }
-
-        var badUserNameChars = [':'];
-
-        for (var i = 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 used only for function, it has no impact on
-   the validation process.
-
-.. seealso::
-
-   CouchDB Guide:
-    - `Validation Functions <http://guide.couchdb.org/editions/1/en/validation.html>`_
-
-   CouchDB Wiki:
-    - `Document Update Validation <http://wiki.apache.org/couchdb/Document_Update_Validation>`_

http://git-wip-us.apache.org/repos/asf/couchdb/blob/cdac7299/share/doc/src/couchapp/index.rst
----------------------------------------------------------------------
diff --git a/share/doc/src/couchapp/index.rst b/share/doc/src/couchapp/index.rst
deleted file mode 100644
index 0985d49..0000000
--- a/share/doc/src/couchapp/index.rst
+++ /dev/null
@@ -1,31 +0,0 @@
-.. Licensed under the Apache License, Version 2.0 (the "License"); you may not
-.. use this file except in compliance with the License. You may obtain a copy of
-.. the License at
-..
-..   http://www.apache.org/licenses/LICENSE-2.0
-..
-.. Unless required by applicable law or agreed to in writing, software
-.. distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-.. WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-.. License for the specific language governing permissions and limitations under
-.. the License.
-
-.. _couchapp:
-
-========
-CouchApp
-========
-
-`CouchApps`_ are web applications served directly from CouchDB, mostly driven by
-JavaScript and HTML5. If you can fit your application into those constraints,
-then you get CouchDB's scalability and flexibility "for free" (and deploying
-your app is as simple as replicating it to the production server).
-
-.. _CouchApps: http://couchapp.org/
-
-.. toctree::
-   :maxdepth: 2
-
-   ddocs
-   views/index
-

http://git-wip-us.apache.org/repos/asf/couchdb/blob/cdac7299/share/doc/src/couchapp/views/collation.rst
----------------------------------------------------------------------
diff --git a/share/doc/src/couchapp/views/collation.rst b/share/doc/src/couchapp/views/collation.rst
deleted file mode 100644
index 9b11b15..0000000
--- a/share/doc/src/couchapp/views/collation.rst
+++ /dev/null
@@ -1,261 +0,0 @@
-.. Licensed under the Apache License, Version 2.0 (the "License"); you may not
-.. use this file except in compliance with the License. You may obtain a copy of
-.. the License at
-..
-..   http://www.apache.org/licenses/LICENSE-2.0
-..
-.. Unless required by applicable law or agreed to in writing, software
-.. distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-.. WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-.. License for the specific language governing permissions and limitations under
-.. the License.
-
-
-.. _views/collation:
-
-===============
-Views Collation
-===============
-
-Basics
-======
-
-View functions specify a key and a value to be returned for each row. CouchDB
-collates the view rows by this key. In the following example, the ``LastName``
-property serves as the key, thus the result will be sorted by ``LastName``:
-
-.. code-block:: javascript
-
-  function(doc) {
-    if (doc.Type == "customer") {
-      emit(doc.LastName, {FirstName: doc.FirstName, Address: doc.Address});
-    }
-  }
-
-CouchDB allows arbitrary JSON structures to be used as keys. You can use JSON
-arrays as keys for fine-grained control over sorting and grouping.
-
-Examples
-========
-
-The following clever trick would return both customer and order documents.
-The key is composed of a customer ``_id`` and a sorting token. Because the key
-for order documents begins with the ``_id`` of a customer document, all the
-orders will be sorted by customer. Because the sorting token for customers is
-lower than the token for orders, the customer document will come before the
-associated orders. The values 0 and 1 for the sorting token are arbitrary.
-
-.. code-block:: javascript
-
-  function(doc) {
-    if (doc.Type == "customer") {
-      emit([doc._id, 0], null);
-    } else if (doc.Type == "order") {
-      emit([doc.customer_id, 1], null);
-    }
-  }
-
-To list a specific customer with ``_id`` XYZ, and all of that customer's orders, limit the startkey and endkey ranges to cover only documents for that customer's ``_id``::
-
-  startkey=["XYZ"]&endkey=["XYZ", {}]
-
-It is not recommended to emit the document itself in the view. Instead, to include the bodies of the documents when requesting the view, request the view with ``?include_docs=true``.
-
-Sorting by Dates
-================
-
-It maybe be convenient to store date attributes in a human readable format
-(i.e. as a `string`), but still sort by date. This can be done by converting
-the date to a `number` in the :js:func:`emit` function. For example, given
-a document with a created_at attribute of ``'Wed Jul 23 16:29:21 +0100 2013'``,
-the following emit function would sort by date:
-
-.. code-block:: javascript
-
-  emit(Date.parse(doc.created_at).getTime(), null);
-
-Alternatively, if you use a date format which sorts lexicographically,
-such as ``"2013/06/09 13:52:11 +0000"`` you can just
-
-.. code-block:: javascript
-
-  emit(doc.created_at, null);
-
-and avoid the conversion. As a bonus, this date format is compatible with the
-JavaScript date parser, so you can use ``new Date(doc.created_at)`` in your
-client side JavaScript to make date sorting easy in the browser.
-
-String Ranges
-=============
-
-If you need start and end keys that encompass every string with a given prefix,
-it is better to use a high value unicode character, than to use a ``'ZZZZ'``
-suffix.
-
-That is, rather than::
-
-  startkey="abc"&endkey="abcZZZZZZZZZ"
-
-You should use::
-
-  startkey="abc"&endkey="abc\ufff0"
-
-Collation Specification
-=======================
-
-This section is based on the view_collation function in `view_collation.js`_:
-
-.. _view_collation.js: https://git-wip-us.apache.org/repos/asf?p=couchdb.git;a=blob;f=share/www/script/test/view_collation.js;hb=HEAD
-
-.. code-block:: javascript
-
-  // special values sort before all other types
-  null
-  false
-  true
-
-  // then numbers
-  1
-  2
-  3.0
-  4
-
-  // then text, case sensitive
-  "a"
-  "A"
-  "aa"
-  "b"
-  "B"
-  "ba"
-  "bb"
-
-  // then arrays. compared element by element until different.
-  // Longer arrays sort after their prefixes
-  ["a"]
-  ["b"]
-  ["b","c"]
-  ["b","c", "a"]
-  ["b","d"]
-  ["b","d", "e"]
-
-  // then object, compares each key value in the list until different.
-  // larger objects sort after their subset objects.
-  {a:1}
-  {a:2}
-  {b:1}
-  {b:2}
-  {b:2, a:1} // Member order does matter for collation.
-             // CouchDB preserves member order
-             // but doesn't require that clients will.
-             // this test might fail if used with a js engine
-             // that doesn't preserve order
-  {b:2, c:2}
-
-Comparison of strings is done using `ICU`_ which implements the
-`Unicode Collation Algorithm`_, giving a dictionary sorting of keys.
-This can give surprising results if you were expecting ASCII ordering.
-Note that:
-
-- All symbols sort before numbers and letters (even the "high" symbols like
-  tilde, ``0x7e``)
-
-- Differing sequences of letters are compared without regard to case, so
-  ``a < aa`` but also ``A < aa`` and ``a < AA``
-
-- Identical sequences of letters are compared with regard to case, with
-  lowercase before uppercase, so ``a < A``
-
-.. _ICU: http://site.icu-project.org/
-.. _Unicode Collation Algorithm: http://www.unicode.org/unicode/reports/tr10/
-
-You can demonstrate the collation sequence for 7-bit ASCII characters like this:
-
-.. code-block:: ruby
-
-  require 'rubygems'
-  require 'restclient'
-  require 'json'
-
-  DB="http://127.0.0.1:5984/collator"
-
-  RestClient.delete DB rescue nil
-  RestClient.put "#{DB}",""
-
-  (32..126).each do |c|
-    RestClient.put "#{DB}/#{c.to_s(16)}", {"x"=>c.chr}.to_json
-  end
-
-  RestClient.put "#{DB}/_design/test", <<EOS
-  {
-    "views":{
-      "one":{
-        "map":"function (doc) { emit(doc.x,null); }"
-      }
-    }
-  }
-  EOS
-
-  puts RestClient.get("#{DB}/_design/test/_view/one")
-
-This shows the collation sequence to be::
-
-  ` ^ _ - , ; : ! ? . ' " ( ) [ ] { } @ * / \ & # % + < = > | ~ $ 0 1 2 3 4 5 6 7 8 9
-  a A b B c C d D e E f F g G h H i I j J k K l L m M n N o O p P q Q r R s S t T u U v V w W x X y Y z Z
-
-Key ranges
-----------
-
-Take special care when querying key ranges. For example: the query::
-
-  startkey="Abc"&endkey="AbcZZZZ"
-
-will match "ABC" and "abc1", but not "abc". This is because UCA sorts as::
-
-  abc < Abc < ABC < abc1 < AbcZZZZZ
-
-For most applications, to avoid problems you should lowercase the `startkey`::
-
-  startkey="abc"&endkey="abcZZZZZZZZ"
-
-will match all keys starting with ``[aA][bB][cC]``
-
-Complex keys
-------------
-
-The query ``startkey=["foo"]&endkey=["foo",{}]`` will match most array keys
-with "foo" in the first element, such as ``["foo","bar"]`` and
-``["foo",["bar","baz"]]``. However it will not match ``["foo",{"an":"object"}]``
-
-_all_docs
-=========
-
-The :ref:`_all_docs <api/db/all_docs>`  view is a special case because it uses
-ASCII collation for doc ids, not UCA::
-
-  startkey="_design/"&endkey="_design/ZZZZZZZZ"
-
-will not find ``_design/abc`` because `'Z'` comes before `'a'` in the ASCII
-sequence. A better solution is::
-
-  startkey="_design/"&endkey="_design0"
-
-Raw collation
-=============
-
-To squeeze a little more performance out of views, you can specify
-``"options":{"collation":"raw"}``  within the view definition for native Erlang
-collation, especially if you don't require UCA. This gives a different collation
-sequence:
-
-.. code-block:: javascript
-
-  1
-  false
-  null
-  true
-  {"a":"a"},
-  ["a"]
-  "a"
-
-Beware that ``{}`` is no longer a suitable "high" key sentinel value. Use a
-string like ``"\ufff0"`` instead.

http://git-wip-us.apache.org/repos/asf/couchdb/blob/cdac7299/share/doc/src/couchapp/views/index.rst
----------------------------------------------------------------------
diff --git a/share/doc/src/couchapp/views/index.rst b/share/doc/src/couchapp/views/index.rst
deleted file mode 100644
index 05f476d..0000000
--- a/share/doc/src/couchapp/views/index.rst
+++ /dev/null
@@ -1,30 +0,0 @@
-.. Licensed under the Apache License, Version 2.0 (the "License"); you may not
-.. use this file except in compliance with the License. You may obtain a copy of
-.. the License at
-..
-..   http://www.apache.org/licenses/LICENSE-2.0
-..
-.. Unless required by applicable law or agreed to in writing, software
-.. distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-.. WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-.. License for the specific language governing permissions and limitations under
-.. the License.
-
-
-.. _views:
-
-==============
-Guide to Views
-==============
-
-Views are the primary tool used for querying and reporting on CouchDB documents.
-There you'll learn how they works and how to use them to build effective
-applications with CouchDB
-
-.. toctree::
-
-  intro
-  collation
-  joins
-  nosql
-  pagination

http://git-wip-us.apache.org/repos/asf/couchdb/blob/cdac7299/share/doc/src/couchapp/views/intro.rst
----------------------------------------------------------------------
diff --git a/share/doc/src/couchapp/views/intro.rst b/share/doc/src/couchapp/views/intro.rst
deleted file mode 100644
index 5d588ed..0000000
--- a/share/doc/src/couchapp/views/intro.rst
+++ /dev/null
@@ -1,675 +0,0 @@
-.. Licensed under the Apache License, Version 2.0 (the "License"); you may not
-.. use this file except in compliance with the License. You may obtain a copy of
-.. the License at
-..
-..   http://www.apache.org/licenses/LICENSE-2.0
-..
-.. Unless required by applicable law or agreed to in writing, software
-.. distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-.. WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-.. License for the specific language governing permissions and limitations under
-.. the License.
-
-
-.. _views/intro:
-
-===========================
-Introduction Into The Views
-===========================
-
-Views are useful for many purposes:
-
-- Filtering the documents in your database to find those relevant to a
-  particular process.
-- Extracting data from your documents and presenting it in a specific order.
-- Building efficient indexes to find documents by any value or structure that
-  resides in them.
-- Use these indexes to represent relationships among documents.
-- Finally, with views you can make all sorts of calculations on the data in your
-  documents. For example, if documents represent your company’s financial
-  transactions, a view can answer the question of what the spending was in the
-  last week, month, or year.
-
-What Is a View?
-===============
-
-Let’s go through the different use cases. First is extracting data that you
-might need for a special purpose in a specific order. For a front page, we want
-a list of blog post titles sorted by date. We’ll work with a set of example
-documents as we walk through how views work:
-
-.. code-block:: javascript
-
-  {
-    "_id":"biking",
-    "_rev":"AE19EBC7654",
-
-    "title":"Biking",
-    "body":"My biggest hobby is mountainbiking. The other day...",
-    "date":"2009/01/30 18:04:11"
-  }
-
-.. code-block:: javascript
-
-  {
-    "_id":"bought-a-cat",
-    "_rev":"4A3BBEE711",
-
-    "title":"Bought a Cat",
-    "body":"I went to the the pet store earlier and brought home a little kitty...",
-    "date":"2009/02/17 21:13:39"
-  }
-
-.. code-block:: javascript
-
-  {
-    "_id":"hello-world",
-    "_rev":"43FBA4E7AB",
-
-    "title":"Hello World",
-    "body":"Well hello and welcome to my new blog...",
-    "date":"2009/01/15 15:52:20"
-  }
-
-Three will do for the example. Note that the documents are sorted by "_id",
-which is how they are stored in the database. Now we define a view.
-Bear with us without an explanation while we show you some code:
-
-.. code-block:: javascript
-
-  function(doc) {
-    if(doc.date && doc.title) {
-      emit(doc.date, doc.title);
-    }
-  }
-
-This is a `map function`, and it is written in JavaScript. If you are not
-familiar with JavaScript but have used C or any other C-like language such as
-Java, PHP, or C#, this should look familiar. It is a simple function definition.
-
-You provide CouchDB with view functions as strings stored inside the ``views``
-field of a design document. You don’t run it yourself. Instead, when you
-`query your view`, CouchDB takes the source code and runs it for you on every
-document in the database your view was defined in. You `query your view` to
-retrieve the `view result`.
-
-All map functions have a single parameter doc. This is a single document in
-the database. Our map function checks whether our document has a ``date`` and
-a ``title`` attribute — luckily, all of our documents have them — and then calls
-the built-in :js:func:`emit` function with these two attributes as arguments.
-
-The :js:func:`emit` function always takes two arguments: the first is ``key``,
-and the second is ``value``. The ``emit(key, value)`` function creates an entry
-in our `view result`. One more thing: the ``emit()`` function can be called
-multiple times in the map function to create multiple entries in the view
-results from a single document, but we are not doing that yet.
-
-CouchDB takes whatever you pass into the emit() function and puts it into a list
-(see Table 1, “View results” below). Each row in that list includes the `key`
-and `value`. More importantly, the list is sorted by key (by ``doc.date``
-in our case).  The most important feature of a view result is that it is sorted
-by `key`. We will come back to that over and over again to do neat things. Stay
-tuned.
-
-Table 1. View results:
-
-+-----------------------+------------------+
-|         Key           |      Value       |
-+=======================+==================+
-| "2009/01/15 15:52:20" | "Hello World"    |
-+-----------------------+------------------+
-| "2009/01/30 18:04:11" | "Biking"         |
-+-----------------------+------------------+
-| "2009/02/17 21:13:39" | "Bought a Cat"   |
-+-----------------------+------------------+
-
-
-When you query your view, CouchDB takes the source code and runs it for you on
-every document in the database. If you have a lot of documents, that takes
-quite a bit of time and you might wonder if it is not horribly inefficient
-to do this. Yes, it would be, but CouchDB is designed to avoid any extra costs:
-it only runs through all documents once, when you first query your view.
-If a document is changed, the map function is only run once, to recompute
-the keys and values for that single document.
-
-The view result is stored in a B-tree, just like the structure that is
-responsible for holding your documents. View B-trees are stored in their
-own file, so that for high-performance CouchDB usage, you can keep views on
-their own disk. The B-tree provides very fast lookups of rows by key, as well
-as efficient streaming of rows in a key range. In our example, a single view
-can answer all questions that involve time: “Give me all the blog posts from
-last week” or “last month” or “this year.” Pretty neat.
-
-When we query our view, we get back a list of all documents sorted by date.
-Each row also includes the post title so we can construct links to posts.
-Table 1 is just a graphical representation of the view result.
-The actual result is JSON-encoded and contains a little more metadata:
-
-.. code-block:: javascript
-
-  {
-    "total_rows": 3,
-    "offset": 0,
-    "rows": [
-      {
-        "key": "2009/01/15 15:52:20",
-        "id": "hello-world",
-        "value": "Hello World"
-      },
-
-      {
-        "key": "2009/01/30 18:04:11",
-        "id": "biking",
-        "value": "Biking"
-      },
-
-      {
-        "key": "2009/02/17 21:13:39",
-        "id": "bought-a-cat",
-        "value": "Bought a Cat"
-      }
-
-    ]
-  }
-
-Now, the actual result is not as nicely formatted and doesn’t include any
-superfluous whitespace or newlines, but this is better for you (and us!)
-to read and understand. Where does that "id" member in the result rows come
-from? That wasn’t there before. That’s because we omitted it earlier to avoid
-confusion. CouchDB automatically includes the document ID of the document that
-created the entry in the view result. We’ll use this as well when constructing
-links to the blog post pages.
-
-Efficient Lookups
-=================
-
-Let’s move on to the second use case for views: “building efficient indexes to
-find documents by any value or structure that resides in them.” We already
-explained the efficient indexing, but we skipped a few details. This is a good
-time to finish this discussion as we are looking at map functions that are a
-little more complex.
-
-First, back to the B-trees! We explained that the B-tree that backs the
-key-sorted view result is built only once, when you first query a view,
-and all subsequent queries will just read the B-tree instead of executing
-the map function for all documents again. What happens, though, when you change
-a document, add a new one, or delete one? Easy: CouchDB is smart enough
-to find the rows in the view result that were created by a specific document.
-It marks them invalid so that they no longer show up in view results.
-If the document was deleted, we’re good — the resulting B-tree reflects the
-state of the database. If a document got updated, the new document is run
-through the map function and the resulting new lines are inserted into
-the B-tree at the correct spots. New documents are handled in the same way.
-The B-tree is a very efficient data structure for our needs, and the crash-only
-design of CouchDB databases is carried over to the view indexes as well.
-
-To add one more point to the efficiency discussion: usually multiple documents
-are updated between view queries. The mechanism explained in the previous
-paragraph gets applied to all changes in the database since the last time
-the view was queried in a batch operation, which makes things even faster and
-is generally a better use of your resources.
-
-Find One
---------
-
-On to more complex map functions. We said “find documents by any value or
-structure that resides in them.” We already explained how to extract a value
-by which to sort a list of views (our date field). The same mechanism is used
-for fast lookups. The URI to query to get a view’s result is
-``/database/_design/designdocname/_view/viewname``. This gives you a list of all
-rows in the view. We have only three documents, so things are small, but with
-thousands of documents, this can get long. You can add view parameters to the
-URI to constrain the result set. Say we know the date of a blog post.
-To find a single document, we would use
-``/blog/_design/docs/_view/by_date?key="2009/01/30 18:04:11"``
-to get the “Biking” blog post. Remember that you can place whatever you like
-in the key parameter to the emit() function. Whatever you put in there, we can
-now use to look up exactly — and fast.
-
-Note that in the case where multiple rows have the same key (perhaps we design
-a view where the key is the name of the post’s author), key queries can return
-more than one row.
-
-Find Many
----------
-
-We talked about “getting all posts for last month.” If it’s February now,
-this is as easy as ``/blog/_design/docs/_view/by_date?startkey="2010/01/01 00:00:00"&endkey="2010/02/00 00:00:00"``.
-The ``startkey`` and ``endkey`` parameters specify an inclusive range on which
-we can search.
-
-To make things a little nicer and to prepare for a future example, we are going
-to change the format of our date field. Instead of a string, we are going to use
-an array, where individual members are part of a timestamp in decreasing
-significance. This sounds fancy, but it is rather easy. Instead of::
-
-  {
-    "date": "2009/01/31 00:00:00"
-  }
-
-we use::
-
-  {
-    "date": [2009, 1, 31, 0, 0, 0]
-  }
-
-Our map function does not have to change for this, but our view result looks
-a little different:
-
-Table 2. New view results:
-
-+---------------------------+------------------+
-|            Key            |      Value       |
-+===========================+==================+
-| [2009, 1, 15, 15, 52, 20] | "Hello World"    |
-+---------------------------+------------------+
-| [2009, 2, 17, 21, 13, 39] | "Biking"         |
-+---------------------------+------------------+
-| [2009, 1, 30, 18, 4, 11]  | "Bought a Cat"   |
-+---------------------------+------------------+
-
-
-And our queries change to ``/blog/_design/docs/_view/by_date?startkey=[2010, 1, 1, 0, 0, 0]&endkey=[2010, 2, 1, 0, 0, 0]``.
-For all you care, this is just a change in syntax, not meaning. But it shows
-you the power of views. Not only can you construct an index with scalar values
-like strings and integers, you can also use JSON structures as keys for your
-views. Say we tag our documents with a list of tags and want to see all tags,
-but we don’t care for documents that have not been tagged.
-
-.. code-block:: javascript
-
-  {
-    ...
-    tags: ["cool", "freak", "plankton"],
-    ...
-  }
-
-.. code-block:: javascript
-
-  {
-    ...
-    tags: [],
-    ...
-  }
-
-.. code-block:: javascript
-
-  function(doc) {
-    if(doc.tags.length > 0) {
-      for(var idx in doc.tags) {
-        emit(doc.tags[idx], null);
-      }
-    }
-  }
-
-
-This shows a few new things. You can have conditions on structure
-(``if(doc.tags.length > 0)``) instead of just values. This is also an example of
-how a map function calls :js:func:`emit` multiple times per document.
-And finally, you can pass null instead of a value to the value parameter.
-The same is true for the key parameter. We’ll see in a bit how that is useful.
-
-Reversed Results
-----------------
-
-To retrieve view results in reverse order, use the ``descending=true`` query
-parameter. If you are using a ``startkey`` parameter, you will find that CouchDB
-returns different rows or no rows at all. What’s up with that?
-
-It’s pretty easy to understand when you see how view query options work under
-the hood. A view is stored in a tree structure for fast lookups. Whenever you
-query a view, this is how CouchDB operates:
-
-#. Starts reading at the top, or at the position that ``startkey`` specifies,
-   if present.
-#. Returns one row at a time until the end or until it hits ``endkey``,
-   if present.
-
-If you specify ``descending=true``, the reading direction is reversed,
-not the sort  order of the rows in the view. In addition, the same two-step
-procedure is followed.
-
-Say you have a view result that looks like this:
-
-+-----+-------+
-| Key | Value |
-+=====+=======+
-|  0  | "foo" |
-+-----+-------+
-|  1  | "bar" |
-+-----+-------+
-|  2  | "baz" |
-+-----+-------+
-
-Here are potential query options: ``?startkey=1&descending=true``. What will
-CouchDB do? See #1 above: it jumps to ``startkey``, which is the row with the
-key ``1``, and starts reading backward until it hits the end of the view.
-So the particular result would be:
-
-+-----+-------+
-| Key | Value |
-+=====+=======+
-|  1  | "bar" |
-+-----+-------+
-|  0  | "foo" |
-+-----+-------+
-
-This is very likely not what you want. To get the rows with the indexes ``1``
-and ``2`` in reverse order, you need to switch the ``startkey`` to ``endkey``:
-``endkey=1&descending=true``:
-
-+-----+-------+
-| Key | Value |
-+=====+=======+
-|  2  | "baz" |
-+-----+-------+
-|  1  | "bar" |
-+-----+-------+
-
-Now that looks a lot better. CouchDB started reading at the bottom of the view
-and went backward until it hit ``endkey``.
-
-The View to Get Comments for Posts
-==================================
-
-We use an array key here to support the ``group_level`` reduce query parameter.
-CouchDB’s views are stored in the B-tree file structure. Because of the way
-B-trees are structured, we can cache the intermediate reduce results in the
-non-leaf nodes of the tree, so reduce queries can be computed along arbitrary
-key ranges in logarithmic time. See Figure 1, “Comments map function”.
-
-In the blog app, we use ``group_level`` reduce queries to compute the count of
-comments both on a per-post and total basis, achieved by querying the same view
-index with different methods. With some array keys, and assuming each key has
-the value ``1``:
-
-.. code-block:: javascript
-
-  ["a","b","c"]
-  ["a","b","e"]
-  ["a","c","m"]
-  ["b","a","c"]
-  ["b","a","g"]
-
-the reduce view:
-
-.. code-block:: javascript
-
-  function(keys, values, rereduce) {
-    return sum(values)
-  }
-
-returns the total number of rows between the start and end key.
-So with ``startkey=["a","b"]&endkey=["b"]`` (which includes the first three of
-the above keys) the result would equal ``3``. The effect is to count rows.
-If you’d like to count rows without depending on the row value, you can switch
-on the ``rereduce`` parameter:
-
-.. code-block:: javascript
-
-  function(keys, values, rereduce) {
-    if (rereduce) {
-      return sum(values);
-    } else {
-      return values.length;
-    }
-  }
-
-.. note::
-
-   JavaScript function about could be effectively replaced by builtin ``_count``
-   one.
-
-.. figure:: ../../../images/views-intro-01.png
-   :align: center
-   :scale: 50 %
-   :alt:  Comments map function
-
-   Figure 1. Comments map function
-
-
-This is the reduce view used by the example app to count comments, while
-utilizing the map to output the comments, which are more useful than just
-``1`` over and over. It pays to spend some time playing around with map and
-reduce functions. Futon is OK for this, but it doesn’t give full access to all
-the query parameters. Writing your own test code for views in your language
-of choice is a great way to explore the nuances and capabilities of CouchDB’s
-incremental MapReduce system.
-
-Anyway, with a ``group_level`` query, you’re basically running a series of
-reduce range queries: one for each group that shows up at the level you query.
-Let’s reprint the key list from earlier, grouped at level ``1``:
-
-.. code-block:: javascript
-
-  ["a"]   3
-  ["b"]   2
-
-And at ``group_level=2``:
-
-.. code-block:: javascript
-
-  ["a","b"]   2
-  ["a","c"]   1
-  ["b","a"]   2
-
-Using the parameter ``group=true`` makes it behave as though it were
-``group_level=exact``, so in the case of our current example, it would give the
-number ``1`` for each key, as there are no exactly duplicated keys.
-
-Reduce/Rereduce
-===============
-
-We briefly talked about the ``rereduce`` parameter to your reduce function.
-We’ll explain what’s up with it in this section. By now, you should have learned
-that your view result is stored in B-tree index structure for efficiency.
-The existence and use of the ``rereduce`` parameter is tightly coupled to how
-the B-tree index works.
-
-Consider the map result are:
-
-.. code-block:: javascript
-
-  "afrikan", 1
-  "afrikan", 1
-  "chinese", 1
-  "chinese", 1
-  "chinese", 1
-  "chinese", 1
-  "french", 1
-  "italian", 1
-  "italian", 1
-  "spanish", 1
-  "vietnamese", 1
-  "vietnamese", 1
-
-Example 1. Example view result (mmm, food)
-
-When we want to find out how many dishes there are per origin, we can reuse
-the simple reduce function shown earlier:
-
-.. code-block:: javascript
-
-  function(keys, values, rereduce) {
-    return sum(values);
-  }
-
-Figure 2, “The B-tree index” shows a simplified version of what the B-tree index
-looks like. We abbreviated the key strings.
-
-.. figure:: ../../../images/views-intro-02.png
-   :align: center
-   :alt: The B-tree index
-
-   Figure 2. The B-tree index
-
-The view result is what computer science grads call a “pre-order” walk through
-the tree. We look at each element in each node starting from the left. Whenever
-we see that there is a subnode to descend into, we descend and start reading
-the elements in that subnode. When we have walked through the entire tree,
-we’re done.
-
-You can see that CouchDB stores both keys and values inside each leaf node.
-In our case, it is simply always ``1``, but you might have a value where you
-count other results and then all rows have a different value. What’s important
-is that CouchDB runs all elements that are within a node into the reduce
-function (setting the ``rereduce`` parameter to false) and stores the result
-inside the parent node along with the edge to the subnode. In our case, each
-edge has a 3 representing the reduce value for the node it points to.
-
-.. note::
-
-   In reality, nodes have more than 1,600 elements in them. CouchDB computes
-   the result for all the elements in multiple iterations over the elements in
-   a single node, not all at once (which would be disastrous for memory
-   consumption).
-
-Now let’s see what happens when we run a query. We want to know how many
-"chinese" entries we have. The query option is simple: ``?key="chinese"``.
-See Figure 3, “The B-tree index reduce result”.
-
-.. figure:: ../../../images/views-intro-03.png
-   :align: center
-   :alt: The B-tree index reduce result
-
-   Figure 3. The B-tree index reduce result
-
-CouchDB detects that all values in the subnode include the "chinese" key.
-It concludes that it can take just the 3 values associated with that node to
-compute the final result. It then finds the node left to it and sees that it’s
-a node with keys outside the requested range (``key=`` requests a range where
-the beginning and the end are the same value). It concludes that it has to use
-the "chinese" element’s value and the other node’s value and run them through
-the reduce function with the ``rereduce`` parameter set to true.
-
-The reduce function effectively calculates 3 + 1 on query time and returns the
-desired result. The next example shows some pseudocode that shows the last
-invocation of the reduce function with actual values:
-
-.. code-block:: javascript
-
-  function(null, [3, 1], true) {
-    return sum([3, 1]);
-  }
-
-
-Now, we said your reduce function must actually reduce your values. If you see
-the B-tree, it should become obvious what happens when you don’t reduce your
-values. Consider the following map result and reduce function. This time we
-want to get a list of all the unique labels in our view:
-
-.. code-block:: javascript
-
-  "abc", "afrikan"
-  "cef", "afrikan"
-  "fhi", "chinese"
-  "hkl", "chinese"
-  "ino", "chinese"
-  "lqr", "chinese"
-  "mtu", "french"
-  "owx", "italian"
-  "qza", "italian"
-  "tdx", "spanish"
-  "xfg", "vietnamese"
-  "zul", "vietnamese"
-
-We don’t care for the key here and only list all the labels we have. Our reduce
-function removes duplicates:
-
-.. code-block:: javascript
-
-  function(keys, values, rereduce) {
-    var unique_labels = {};
-    values.forEach(function(label) {
-      if(!unique_labels[label]) {
-        unique_labels[label] = true;
-      }
-    });
-
-    return unique_labels;
-  }
-
-
-This translates to Figure 4, “An overflowing reduce index”.
-
-We hope you get the picture. The way the B-tree storage works means that if you
-don’t actually reduce your data in the reduce function, you end up having
-CouchDB copy huge amounts of data around that grow linearly, if not faster
-with the number of rows in your view.
-
-CouchDB will be able to compute the final result, but only for views with a few
-rows. Anything larger will experience a ridiculously slow view build time.
-To help with that, CouchDB since version 0.10.0 will throw an error if your
-reduce function does not reduce its input values.
-
-.. figure:: ../../../images/views-intro-04.png
-   :align: center
-   :alt: An overflowing reduce index
-
-   Figure 4. An overflowing reduce index
-
-
-Lessons Learned
-===============
-
-- If you don’t use the key field in the map function, you are probably doing it
-  wrong.
-- If you are trying to make a list of values unique in the reduce functions,
-  you are probably doing it wrong.
-- If you don’t reduce your values to a single scalar value or a small
-  fixed-sized object or array with a fixed number of scalar values of small
-  sizes, you are probably doing it wrong.
-
-Wrapping Up
-===========
-
-Map functions are side effect–free functions that take a document as argument
-and `emit` key/value pairs. CouchDB stores the emitted rows by constructing a
-sorted B-tree index, so row lookups by key, as well as streaming operations
-across a range of rows, can be accomplished in a small memory and processing
-footprint, while writes avoid seeks. Generating a view takes ``O(N)``, where
-``N`` is the total number of rows in the view. However, querying a view is very
-quick, as the B-tree remains shallow even when it contains many, many keys.
-
-Reduce functions operate on the sorted rows emitted by map view functions.
-CouchDB’s reduce functionality takes advantage of one of the fundamental
-properties of B-tree indexes: for every leaf node (a sorted row), there is a
-chain of internal nodes reaching back to the root. Each leaf node in the B-tree
-carries a few rows (on the order of tens, depending on row size), and each
-internal node may link to a few leaf nodes or other internal nodes.
-
-The reduce function is run on every node in the tree in order to calculate
-the final reduce value. The end result is a reduce function that can be
-incrementally updated upon changes to the map function, while recalculating
-the reduction values for a minimum number of nodes. The initial reduction is
-calculated once per each node (inner and leaf) in the tree.
-
-When run on leaf nodes (which contain actual map rows), the reduce function’s
-third parameter, ``rereduce``, is false. The arguments in this case are the keys
-and values as output by the map function. The function has a single returned
-reduction value, which is stored on the inner node that a working set of leaf
-nodes have in common, and is used as a cache in future reduce calculations.
-
-When the reduce function is run on inner nodes, the ``rereduce`` flag is
-``true``. This allows the function to account for the fact that it will be
-receiving its own prior output. When ``rereduce`` is true, the values passed to
-the function are intermediate reduction values as cached from previous
-calculations. When the tree is more than two levels deep, the `rereduce` phase
-is repeated, consuming chunks of the previous level’s output until the final
-reduce value is calculated at the root node.
-
-A common mistake new CouchDB users make is attempting to construct complex
-aggregate values with a reduce function. Full reductions should result in a
-scalar value, like 5, and not, for instance, a JSON hash with a set of unique
-keys and the count of each. The problem with this approach is that you’ll end
-up with a very large final value. The number of unique keys can be nearly as
-large as the number of total keys, even for a large set. It is fine to combine
-a few scalar calculations into one reduce function; for instance, to find the
-total, average, and standard deviation of a set of numbers in a single function.
-
-If you’re interested in pushing the edge of CouchDB’s incremental reduce
-functionality, have a look at `Google’s paper on Sawzall`_, which gives examples
-of some of the more exotic reductions that can be accomplished in a system with
-similar constraints.
-
-.. _Google’s paper on Sawzall: http://research.google.com/archive/sawzall.html

http://git-wip-us.apache.org/repos/asf/couchdb/blob/cdac7299/share/doc/src/couchapp/views/joins.rst
----------------------------------------------------------------------
diff --git a/share/doc/src/couchapp/views/joins.rst b/share/doc/src/couchapp/views/joins.rst
deleted file mode 100644
index 3b95427..0000000
--- a/share/doc/src/couchapp/views/joins.rst
+++ /dev/null
@@ -1,430 +0,0 @@
-.. Licensed under the Apache License, Version 2.0 (the "License"); you may not
-.. use this file except in compliance with the License. You may obtain a copy of
-.. the License at
-..
-..   http://www.apache.org/licenses/LICENSE-2.0
-..
-.. Unless required by applicable law or agreed to in writing, software
-.. distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-.. WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-.. License for the specific language governing permissions and limitations under
-.. the License.
-
-
-.. _views/json:
-
-================
-Joins With Views
-================
-
-Linked Documents
-================
-
-If your :ref:`map function <mapfun>` emits an object value which has
-``{'_id': XXX}`` and you :ref:`query view <api/ddoc/view>` with
-``include_docs=true`` parameter, then CouchDB will fetch the document with id
-``XXX`` rather than the document which was processed to emit the key/value pair.
-
-This means that if one document contains the ids of other documents, it can
-cause those documents to be fetched in the view too, adjacent to the same key
-if required.
-
-For example, if you have the following hierarchically-linked documents:
-
-.. code-block:: javascript
-
-  [
-    { "_id": "11111" },
-    { "_id": "22222", "ancestors": ["11111"], "value": "hello" },
-    { "_id": "33333", "ancestors": ["22222","11111"], "value": "world" }
-  ]
-
-You can emit the values with the ancestor documents adjacent to them in the view
-like this:
-
-.. code-block:: javascript
-
-  function(doc) {
-    if (doc.value) {
-      emit([doc.value, 0], null);
-      if (doc.ancestors) {
-        for (var i in doc.ancestors) {
-          emit([doc.value, Number(i)+1], {_id: doc.ancestors[i]});
-        }
-      }
-    }
-  }
-
-The result you get is:
-
-.. code-block:: javascript
-
-  {
-      "total_rows": 5,
-      "offset": 0,
-      "rows": [
-          {
-              "id": "22222",
-              "key": [
-                  "hello",
-                  0
-              ],
-              "value": null,
-              "doc": {
-                  "_id": "22222",
-                  "_rev": "1-0eee81fecb5aa4f51e285c621271ff02",
-                  "ancestors": [
-                      "11111"
-                  ],
-                  "value": "hello"
-              }
-          },
-          {
-              "id": "22222",
-              "key": [
-                  "hello",
-                  1
-              ],
-              "value": {
-                  "_id": "11111"
-              },
-              "doc": {
-                  "_id": "11111",
-                  "_rev": "1-967a00dff5e02add41819138abb3284d"
-              }
-          },
-          {
-              "id": "33333",
-              "key": [
-                  "world",
-                  0
-              ],
-              "value": null,
-              "doc": {
-                  "_id": "33333",
-                  "_rev": "1-11e42b44fdb3d3784602eca7c0332a43",
-                  "ancestors": [
-                      "22222",
-                      "11111"
-                  ],
-                  "value": "world"
-              }
-          },
-          {
-              "id": "33333",
-              "key": [
-                  "world",
-                  1
-              ],
-              "value": {
-                  "_id": "22222"
-              },
-              "doc": {
-                  "_id": "22222",
-                  "_rev": "1-0eee81fecb5aa4f51e285c621271ff02",
-                  "ancestors": [
-                      "11111"
-                  ],
-                  "value": "hello"
-              }
-          },
-          {
-              "id": "33333",
-              "key": [
-                  "world",
-                  2
-              ],
-              "value": {
-                  "_id": "11111"
-              },
-              "doc": {
-                  "_id": "11111",
-                  "_rev": "1-967a00dff5e02add41819138abb3284d"
-              }
-          }
-      ]
-  }
-
-which makes it very cheap to fetch a document plus all its ancestors in one
-query.
-
-Note that the ``"id"`` in the row is still that of the originating document.
-The only difference is that ``include_docs`` fetches a different doc.
-
-The current revision of the document is resolved at query time, not at the time
-the view is generated. This means that if a new revision of the linked document
-is added later, it will appear in view queries even though the view itself
-hasn't changed. To force a specific revision of a linked document to be used,
-emit a ``"_rev"`` property as well as ``"_id"``.
-
-
-Using View Collation
-====================
-
-:Author: Christopher Lenz
-:Date: 2007-10-05
-:Source: http://www.cmlenz.net/archives/2007/10/couchdb-joins
-
-Just today, there was a discussion on IRC how you'd go about modeling a simple
-blogging system with “post” and “comment” entities, where any blog post might
-have N comments. If you'd be using an SQL database, you'd obviously have two
-tables with foreign keys and you'd be using joins. (At least until you needed
-to add some `denormalization`_).
-
-.. _denormalization: http://en.wikipedia.org/wiki/Denormalization
-
-But what would the “obvious” approach in CouchDB look like?
-
-Approach #1: Comments Inlined
------------------------------
-
-A simple approach would be to have one document per blog post, and store the
-comments inside that document:
-
-.. code-block:: javascript
-
-  {
-    "_id": "myslug",
-    "_rev": "123456",
-    "author": "john",
-    "title": "My blog post",
-    "content": "Bla bla bla …",
-    "comments": [
-      {"author": "jack", "content": "…"},
-      {"author": "jane", "content": "…"}
-    ]
-  }
-
-.. note::
-   Of course the model of an actual blogging system would be more extensive,
-   you'd have tags, timestamps, etc etc. This is just to demonstrate the basics.
-
-The obvious advantage of this approach is that the data that belongs together
-is stored in one place. Delete the post, and you automatically delete the
-corresponding comments, and so on.
-
-You may be thinking that putting the comments inside the blog post document
-would not allow us to query for the comments themselves, but you'd be wrong.
-You could trivially write a CouchDB view that would return all comments across
-all blog posts, keyed by author:
-
-.. code-block:: javascript
-
-  function(doc) {
-    for (var i in doc.comments) {
-      emit(doc.comments[i].author, doc.comments[i].content);
-    }
-  }
-
-Now you could list all comments by a particular user by invoking the view and
-passing it a ``?key="username"`` query string parameter.
-
-However, this approach has a drawback that can be quite significant for many
-applications: To add a comment to a post, you need to:
-
-- Fetch the blog post document
-- Add the new comment to the JSON structure
-- Send the updated document to the server
-
-Now if you have multiple client processes adding comments at roughly the same
-time, some of them will get a `HTTP 409 Conflict` error on step 3 (that's
-optimistic concurrency in action). For some applications this makes sense, but
-in many other apps, you'd want to append new related data regardless of whether
-other data has been added in the meantime.
-
-The only way to allow non-conflicting addition of related data is by putting
-that related data into separate documents.
-
-Approach #2: Comments Separate
-------------------------------
-
-Using this approach you'd have one document per blog post, and one document per
-comment. The comment documents would have a “backlink” to the post they belong
-to.
-
-The blog post document would look similar to the above, minus the comments
-property. Also, we'd now have a type property on all our documents so that we
-can tell the difference between posts and comments:
-
-.. code-block:: javascript
-
-  {
-    "_id": "myslug",
-    "_rev": "123456",
-    "type": "post",
-    "author": "john",
-    "title": "My blog post",
-    "content": "Bla bla bla …"
-  }
-
-The comments themselves are stored in separate documents, which also have a type
-property (this time with the value “comment”), and in addition feature a post
-property containing the ID of the post document they belong to:
-
-.. code-block:: javascript
-
-  {
-    "_id": "ABCDEF",
-    "_rev": "123456",
-    "type": "comment",
-    "post": "myslug",
-    "author": "jack",
-    "content": "…"
-  }
-
-.. code-block:: javascript
-
-  {
-    "_id": "DEFABC",
-    "_rev": "123456",
-    "type": "comment",
-    "post": "myslug",
-    "author": "jane",
-    "content": "…"
-  }
-
-To list all comments per blog post, you'd add a simple view, keyed by blog post
-ID:
-
-.. code-block:: javascript
-
-  function(doc) {
-    if (doc.type == "comment") {
-      emit(doc.post, {author: doc.author, content: doc.content});
-    }
-  }
-
-And you'd invoke that view passing it a ``?key="post_id"`` query string
-parameter.
-
-Viewing all comments by author is just as easy as before:
-
-.. code-block:: javascript
-
-  function(doc) {
-    if (doc.type == "comment") {
-      emit(doc.author, {post: doc.post, content: doc.content});
-    }
-  }
-
-So this is better in some ways, but it also has a disadvantage.
-Imagine you want to display a blog post with all the associated comments on the
-same web page. With our first approach, we needed just a single request to the
-CouchDB server, namely a ``GET`` request to the document. With this second
-approach, we need two requests: a ``GET`` request to the post document, and a
-``GET`` request to the view that returns all comments for the post.
-
-That is okay, but not quite satisfactory. Just imagine you wanted to added
-threaded comments: you'd now need an additional fetch per comment. What we'd
-probably want then would be a way to join the blog post and the various comments
-together to be able to retrieve them with a single HTTP request.
-
-This was when Damien Katz, the author of CouchDB, chimed in to the discussion
-on IRC to show us the way.
-
-Optimization: Using the Power of View Collation
------------------------------------------------
-
-Obvious to Damien, but not at all obvious to the rest of us: it's fairly simple
-to make a view that includes both the content of the blog post document, and
-the content of all the comments associated with that post. The way you do that
-is by using `complex keys`. Until now we've been using simple string values for
-the view keys, but in fact they can be arbitrary JSON values, so let's make
-some use of that:
-
-.. code-block:: javascript
-
-  function(doc) {
-    if (doc.type == "post") {
-      emit([doc._id, 0], doc);
-    } else if (doc.type == "comment") {
-      emit([doc.post, 1], doc);
-    }
-  }
-
-Okay, this may be confusing at first. Let's take a step back and look at what
-views in CouchDB are really about.
-
-CouchDB views are basically highly efficient on-disk dictionaries that map keys
-to values, where the key is automatically indexed and can be used to filter
-and/or sort the results you get back from your views. When you “invoke” a view,
-you can say that you're only interested in a subset of the view rows by
-specifying a ``?key=foo`` query string parameter. Or you can specify
-``?startkey=foo`` and/or ``?endkey=bar`` query string parameters to fetch rows
-over a range of keys.
-
-It's also important to note that keys are always used for collating (i.e.
-sorting) the rows. CouchDB has well defined (but as of yet undocumented) rules
-for comparing arbitrary JSON objects for collation. For example, the JSON value
-``["foo", 2]`` is sorted after (considered “greater than”) the values
-``["foo"]`` or ``["foo", 1, "bar"]``, but before e.g. ``["foo", 2, "bar"]``.
-This feature enables a whole class of tricks that are rather non-obvious...
-
-.. seealso::
-
-  :ref:`views/collation`
-
-With that in mind, let's return to the view function above. First note that,
-unlike the previous view functions we've used here, this view handles both
-"post" and "comment" documents, and both of them end up as rows in the same
-view. Also, the key in this view is not just a simple string, but an array.
-The first element in that array is always the ID of the post, regardless of
-whether we're processing an actual post document, or a comment associated with
-a post. The second element is 0 for post documents, and 1 for comment documents.
-
-Let's assume we have two blog posts in our database. Without limiting the view
-results via ``key``, ``startkey``, or ``endkey``, we'd get back something like
-the following:
-
-.. code-block:: javascript
-
-  {
-    "total_rows": 5, "offset": 0, "rows": [{
-        "id": "myslug",
-        "key": ["myslug", 0],
-        "value": {...}
-      }, {
-        "id": "ABCDEF",
-        "key": ["myslug", 1],
-        "value": {...}
-      }, {
-        "id": "DEFABC",
-        "key": ["myslug", 1],
-        "value": {...}
-      }, {
-        "id": "other_slug",
-        "key": ["other_slug", 0],
-        "value": {...}
-      }, {
-        "id": "CDEFAB",
-        "key": ["other_slug", 1],
-        "value": {...}
-      },
-    ]
-  }
-
-.. note::
-   The ``...`` placeholder here would contain the complete JSON encoding of the
-   corresponding document
-
-Now, to get a specific blog post and all associated comments, we'd invoke that
-view with the query string::
-
-  ?startkey=["myslug"]&endkey;=["myslug", 2]
-
-We'd get back the first three rows, those that belong to the ``myslug`` post,
-but not the others. Et voila, we now have the data we need to display a post
-with all associated comments, retrieved via a single ``GET`` request.
-
-You may be asking what the 0 and 1 parts of the keys are for. They're simply
-to ensure that the post document is always sorted before the the associated
-comment documents. So when you get back the results from this view for a
-specific post, you'll know that the first row contains the data for the blog
-post itself, and the remaining rows contain the comment data.
-
-One remaining problem with this model is that comments are not ordered, but
-that's simply because we don't have date/time information associated with them.
-If we had, we'd add the timestamp as third element of the key array, probably
-as ISO date/time strings. Now we would continue using the query string
-``?startkey=["myslug"]&endkey=["myslug", 2]`` to fetch the blog post and all
-associated comments, only now they'd be in chronological order.


Mime
View raw message