blob: a3ca59ea8a0946d3edac379948c324b9caea4187 [file] [log] [blame]
.. 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
=============
Query Servers
=============
.. _queryserver_js:
JavaScript
==========
.. note:: While every design function has access to all JavaScript objects,
the table below describes appropriate usage cases. For example,
you may use :func:`emit` in :ref:`listfun`, but :func:`getRow` is not permitted during :ref:`mapfun`.
+--------------------------------+---------------------------------------------+
| JS Function | Reasonable to use in design doc functions |
+================================+=============================================+
| :func:`emit` | :ref:`mapfun` |
+--------------------------------+---------------------------------------------+
| :func:`getRow` | :ref:`listfun` |
+--------------------------------+---------------------------------------------+
| :data:`JSON` | any |
+--------------------------------+---------------------------------------------+
| :func:`isArray` | any |
+--------------------------------+---------------------------------------------+
| :func:`log` | any |
+--------------------------------+---------------------------------------------+
| :func:`provides` | :ref:`showfun`, :ref:`listfun` |
+--------------------------------+---------------------------------------------+
| :func:`registerType` | :ref:`showfun`, :ref:`listfun` |
+--------------------------------+---------------------------------------------+
| :func:`require` | any, except :ref:`reducefun` |
+--------------------------------+---------------------------------------------+
| :func:`send` | :ref:`listfun` |
+--------------------------------+---------------------------------------------+
| :func:`start` | :ref:`listfun` |
+--------------------------------+---------------------------------------------+
| :func:`sum` | any |
+--------------------------------+---------------------------------------------+
| :func:`toJSON` | any |
+--------------------------------+---------------------------------------------+
Design functions context
------------------------
Each design function executes in a special context of predefined objects,
modules and functions:
.. function:: emit(key, value)
Emits a `key`-`value` pair for further processing by CouchDB after the map
function is done.
:param key: The view key
:param value: The `key`'s associated value
.. code-block:: javascript
function(doc){
emit(doc._id, doc._rev);
}
.. function:: getRow()
Extracts the next row from a related view result.
:return: View result row
:rtype: object
.. code-block:: javascript
function(head, req){
send('[');
row = getRow();
if (row){
send(toJSON(row));
while(row = getRow()){
send(',');
send(toJSON(row));
}
}
return ']';
}
.. data:: JSON
`JSON2 <https://git-wip-us.apache.org/repos/asf?p=couchdb.git;a=blob;f=share/server/json2.js>`_
object.
.. function:: isArray(obj)
A helper function to check if the provided value is an `Array`.
:param obj: Any Javascript value
:return: ``true`` if `obj` is `Array`-typed, ``false`` otherwise
:rtype: boolean
.. function:: log(message)
Log a message to the CouchDB log (at the `INFO` level).
:param message: Message to be logged
.. code-block:: javascript
function(doc){
log('Procesing doc ' + doc['_id']);
emit(doc['_id'], null);
}
After the map function has run, the following line can be found in CouchDB
logs (e.g. at `/var/log/couchdb/couch.log`):
.. code-block:: text
[Sat, 03 Nov 2012 17:38:02 GMT] [info] [<0.7543.0>] OS Process #Port<0.3289> Log :: Processing doc 8d300b86622d67953d102165dbe99467
.. function:: provides(key, func)
Registers callable handler for specified MIME key.
:param key: MIME key previously defined by :func:`registerType`
:param func: MIME type handler
.. function:: registerType(key, *mimes)
Registers list of MIME types by associated `key`.
:param key: MIME types
:param mimes: MIME types enumeration
Predefined mappings (`key`-`array`):
- **all**: ``*/*``
- **text**: ``text/plain; charset=utf-8``, ``txt``
- **html**: ``text/html; charset=utf-8``
- **xhtml**: ``application/xhtml+xml``, ``xhtml``
- **xml**: ``application/xml``, ``text/xml``, ``application/x-xml``
- **js**: ``text/javascript``, ``application/javascript``,
``application/x-javascript``
- **css**: ``text/css``
- **ics**: ``text/calendar``
- **csv**: ``text/csv``
- **rss**: ``application/rss+xml``
- **atom**: ``application/atom+xml``
- **yaml**: ``application/x-yaml``, ``text/yaml``
- **multipart_form**: ``multipart/form-data``
- **url_encoded_form**: ``application/x-www-form-urlencoded``
- **json**: ``application/json``, ``text/x-json``
.. function:: require(path)
Loads CommonJS module by a specified `path`. The path should not start with
a slash.
:param path: A CommonJS module path started from design document root
:return: Exported statements
.. function:: send(chunk)
Sends a single string `chunk` in response.
:param chunk: Text chunk
.. code-block:: javascript
function(head, req){
send('Hello,');
send(' ');
send('Couch');
return !
}
.. function:: start(init_resp)
Initiates chunked response. As an option, a custom
:ref:`response <response_object>` object may be sent at this point.
For `list`-functions only!
.. note::
list functions may set the `HTTP response code` and `headers` by calling
this function. This function must be called before :func:`send`,
:func:`getRow` or a `return` statement; otherwise, the query server will
implicitly call this function with the empty object (``{}``).
.. code-block:: javascript
function(head, req){
start({
"code": 302,
"headers": {
"Location": "http://couchdb.apache.org"
}
});
return "Relax!";
}
.. function:: sum(arr)
Sum `arr`'s items.
:param arr: Array of numbers
:rtype: number
.. function:: toJSON(obj)
Encodes `obj` to JSON string. This is an alias for the ``JSON.stringify``
method.
:param obj: JSON encodable object
:return: JSON string
.. _commonjs:
CommonJS Modules
----------------
Support for `CommonJS Modules <http://wiki.commonjs.org/wiki/Modules/1.1.1>`_
(introduced in CouchDB 0.11.0) allows you to create modular design functions
without the need for duplication of functionality.
Here's a CommonJS module that checks user permissions:
.. code-block:: javascript
function user_context(userctx, secobj) {
var is_admin = function() {
return userctx.indexOf('_admin') != -1;
}
return {'is_admin': is_admin}
}
exports['user'] = user_context
Each module has access to additional global variables:
- **module** (`object`): Contains information about the stored module
- **id** (`string`): The module id; a JSON path in ddoc context
- **current** (`code`): Compiled module code object
- **parent** (`object`): Parent frame
- **exports** (`object`): Export statements
- **exports** (`object`): Shortcut to the ``module.exports`` object
The CommonJS module can be added to a design document, like so:
.. code-block:: javascript
{
"views": {
"lib": {
"security": "function user_context(userctx, secobj) { ... }"
},
"validate_doc_update": "function(newdoc, olddoc, userctx, secobj) {
user = require('lib/security').user(userctx, secobj);
return user.is_admin();
}"
},
"_id": "_design/test"
}
Modules paths are relative to the design document's ``views`` object, but
modules can only be loaded from the object referenced via ``lib``. The
``lib`` structure can still be used for view functions as well, by simply
storing view functions at e.g. ``views.lib.map``, ``views.lib.reduce``, etc.
.. _queryserver_erlang:
Erlang
======
.. warning::
Unlike the JavaScript query server, the Erlang query server does not
run in a sandbox. This means Erlang code has full access to your OS,
filesystem and network, which may lead to security issues. While Erlang
functions are faster than JavaScript ones, you need to be careful
about running them, especially if they were written by someone else.
.. note::
Due to security restrictions, the Erlang query server is disabled by
default. To enable it, you need to edit your `local.ini` to include a
``native_query_servers`` section:
.. code-block:: ini
[native_query_servers]
erlang = {couch_native_process, start_link, []}
Don't forget to restart CouchDB after updating the configuration, and
use the ``language: "erlang"`` property in your Erlang design documents.
.. function:: Emit(Id, Value)
Emits `key`-`value` pairs to view indexer process.
.. code-block:: erlang
fun({Doc}) ->
<<K,_/binary>> = proplists:get_value(<<"_rev">>, Doc, null),
V = proplists:get_value(<<"_id">>, Doc, null),
Emit(<<K>>, V)
end.
.. function:: FoldRows(Fun, Acc)
Helper to iterate over all rows in a list function.
:param Fun: Function object.
:param Acc: The value previously returned by `Fun`.
.. code-block:: erlang
fun(Head, {Req}) ->
Fun = fun({Row}, Acc) ->
Id = couch_util:get_value(<<"id">>, Row),
Send(list_to_binary(io_lib:format("Previous doc id: ~p~n", [Acc]))),
Send(list_to_binary(io_lib:format("Current doc id: ~p~n", [Id]))),
{ok, Id}
end,
FoldRows(Fun, nil),
""
end.
.. function:: GetRow()
Retrieves the next row from a related view result.
.. code-block:: erlang
%% FoldRows background implementation.
%% https://git-wip-us.apache.org/repos/asf?p=couchdb.git;a=blob;f=src/couchdb/couch_native_process.erl;hb=HEAD#l368
%%
foldrows(GetRow, ProcRow, Acc) ->
case GetRow() of
nil ->
{ok, Acc};
Row ->
case (catch ProcRow(Row, Acc)) of
{ok, Acc2} ->
foldrows(GetRow, ProcRow, Acc2);
{stop, Acc2} ->
{ok, Acc2}
end
end.
.. function:: Log(Msg)
:param Msg: Log a message at the `INFO` level.
.. code-block:: erlang
fun({Doc}) ->
<<K,_/binary>> = proplists:get_value(<<"_rev">>, Doc, null),
V = proplists:get_value(<<"_id">>, Doc, null),
Log(lists:flatten(io_lib:format("Hello from ~s doc!", [V]))),
Emit(<<K>>, V)
end.
After the map function has run, the following line can be found in
CouchDB logs (e.g. at `/var/log/couchdb/couch.log`):
.. code-block:: text
[Sun, 04 Nov 2012 11:33:58 GMT] [info] [<0.9144.2>] Hello from 8d300b86622d67953d102165dbe99467 doc!
.. function:: Send(Chunk)
Sends a single string `Chunk` in response.
.. code-block:: erlang
fun(Head, {Req}) ->
Send("Hello,"),
Send(" "),
Send("Couch"),
"!"
end.
The function above produces the following response:
.. code-block:: text
Hello, Couch!
.. function:: Start(Headers)
:param Headers: Proplist of :ref:`response object<response_object>`.
Initialize :ref:`listfun` response. At this point, response code and headers
may be defined. For example, this function redirects to the CouchDB web site:
.. code-block:: erlang
fun(Head, {Req}) ->
Start({[{<<"code">>, 302},
{<<"headers">>, {[
{<<"Location">>, <<"http://couchdb.apache.org">>}]
}}
]}),
"Relax!"
end.