Cloudant logo
Documentation

alt tag API Reference

The Cloudant API reference is intended to be a comprehensive and living catalog of Cloudant’s capabilities. Contributions are welcome through Cloudant Labs on GitHub. The API reference content is built with Slate.

For the cURL samples

There are three ways you can supply the username and password data for a request.

  1. The -u $USERNAME parameter on its own causes cURL to ask you to enter your password interactively on the command line before performing the request. This option is used for the cURL examples in the Cloudant API reference.

  2. [Caution: This option is not secure] Entering the combination parameter -u $USERNAME:$PASSWORD as part of your command means that you are not asked to enter your password interactively. However, a plain text copy of your password appears in the terminal log.

  3. [Caution: This option is not secure] For an https cURL request, you can supply the username and password as part of the URL:
    ... https://$USERNAME:$PASSWORD@$USERNAME.cloudant.com ...
    However, a plain text copy of your password appears in the terminal log.

An alternative approach is to use a hashed version of your username and password combination and supply that data in your cURL command. The Cloudant Blog article Authorized curl, a.k.a acurl explains how to create an acurl command that makes use of this technique, enabling you to enter commands such as:
acurl https://$USERNAME.cloudant.com

HTTP

This section provides details of the HTTP Headers and HTTP Status Codes you need to know when using Cloudant.

HTTP Headers

Because Cloudant uses HTTP for all external communication, you need to ensure that the correct HTTP request headers are supplied and processed on retrieval. This is to ensure that you get the right format and encoding. Different environments and clients are more or less strict on the effect of these HTTP headers, especially when they are not present. Where possible, you should be as specific as possible.

Request headers

The supported HTTP request headers include:

Accept

For example, when sending a request without an explicit Accept header, or when specifying */*:

GET /recipes HTTP/1.1
Host: username.cloudant.com
Accept: */*

The returned headers are similar to the following. Note that the returned content type is text/plain even though the information returned by the request is in JSON format:

Server: CouchDB/1.0.2 (Erlang OTP/R14B)
Date: Thu, 13 Jan 2011 13:39:34 GMT
Content-Type: text/plain;charset=utf-8
Content-Length: 227
Cache-Control: must-revalidate

Specifies the list of accepted data types to be returned by the server (i.e. that are accepted/understandable by the client). The format should be a list of one or more MIME types, separated by colons.

For the majority of requests the definition should be for JSON data (application/json). For attachments you can either specify the MIME type explicitly, or use */* to specify that all file types are supported. If the Accept header is not supplied, then the */* MIME type is assumed (i.e. client accepts all formats).

Explicitly specifying the Accept header:

GET /recipes HTTP/1.1
Host: username.cloudant.com
Accept: application/json

The headers returned include the application/json content type:

Server: CouchDB/1.0.2 (Erlang OTP/R14B)
Date: Thu, 13 Jan 2011 13:40:11 GMT
Content-Type: application/json
Content-Length: 227
Cache-Control: must-revalidate

The use of Accept in queries to Cloudant is not required, but is highly recommended as it helps to ensure that the data returned can be processed by the client.

If you specify a data type using the Accept header, Cloudant will honor the specified type in the Content-type header field returned. For example, if you explicitly request application/json in the Accept of a request, the returned HTTP headers will use the value in the returned Content-type field.

Content-Type

Specifies the content type of the information being supplied within the request. The specification uses MIME type specifications. For the majority of requests this is JSON (application/json). For some settings the MIME type is plain text. When uploading attachments it should be the corresponding MIME type for the attachment or binary (application/octet-stream).

The use of the Content-type on a request is highly recommended.

If-None-Match

This header can optionally be sent to find out whether a document has been modified since it was last read or updated. The value of the If-None-Match header should match the last Etag value received. If the value matches the current revision of the document, the server sends a 304 Not Modified status code and the response will not have a body. If not, you should get a normal 200 response, provided the document still exists and no other errors occur.

Response Headers

Response headers are returned by the server when sending back content and include a number of different header fields, many of which are standard HTTP response header and have no significance to how Cloudant operates. The list of response headers important to Cloudant are listed below.

The supported HTTP response headers include:

The Cloudant design document API and the functions when returning HTML (for example as part of a show or list) enable you to include custom HTTP headers through the headers field of the return object.

Cache-Control

The cache control HTTP response header provides a suggestion for client caching mechanisms on how to treat the returned information. Cloudant typically returns the must-revalidate, which indicates that the information should be revalidated if possible. This is used to ensure that the dynamic nature of the content is correctly updated.

Content-Length

The length (in bytes) of the returned content.

Content-Type

Specifies the MIME type of the returned data. For most request, the returned MIME type is text/plain. All text is encoded in Unicode (UTF-8), and this is explicitly stated in the returned Content-type, as text/plain;charset=utf-8.

Etag

The Etag HTTP header field is used to show the revision for a document or the response from a show function. For documents, the value is identical to the revision of the document. The value can be used with an If-None-Match request header to get a 304 Not Modified response if the revision is still current.

ETags cannot currently be used with views or lists, since the ETags returned from those requests are just random numbers that change on every request.

HTTP Status Codes

With the interface to Cloudant working through HTTP, error codes and statuses are reported using a combination of the HTTP status code number, and corresponding data in the body of the response data.

A list of the error codes returned by Cloudant and generic descriptions of the related errors are provided below. The meaning of different status codes for specific request types are provided in the corresponding API call reference.

Example detail supplied in JSON format, following 404 status code:

{
  "error":"not_found",
  "reason":"no_db_file"
}

Account

Your account is your entry point for Cloudant’s API. You access your account using the address prefix https://$USERNAME.cloudant.com. Your Cloudant dashboard is always https://$USERNAME.cloudant.com/dashboard.html.

If you don’t yet have an account, sign up.

Ping

Example of connecting to your Cloudant account:

GET / HTTP/1.1
HOST: $USERNAME.cloudant.com
curl -u $USERNAME https://$USERNAME.cloudant.com
import cloudant

account = cloudant.Account(USERNAME)
ping = account.get()
print ping.status_code
# 200
var nano = require('nano');
var account = nano("https://$USERNAME:$PASSWORD@$USERNAME.cloudant.com");

account.request(function (err, body) {
  if (!err) {
    console.log(body);
  }
});

To see if your Cloudant account is accessible, make a GET against https://$USERNAME.cloudant.com. If you misspelled your account name, you might get a 503 ‘service unavailable’ error.

Authentication

Authentication means proving who you are. This is typically done by providing your user credentials for verification. There are two ways that clients can provide credentials (authenticate) with Cloudant: Basic authentication and Cookie authentication.

Basic authentication is similar to showing an ID at a door for checking every time you want to enter. Cookie authentication is similar to having a key to the door so that you can let yourself in whenever you want. The key is a cookie named AuthSession.

Basic Authentication

Example of providing basic authentication credentials in a request:

GET /db/document HTTP/1.1
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=
curl https://$USERNAME:$PASSWORD@$USERNAME.cloudant.com
import cloudant

url = "https://{0}:{1}@{0}.cloudant.com".format(USERNAME, PASSWORD)
account = cloudant.Account(url)
ping = account.get()
print ping.status_code
# 200
var nano = require('nano');
var account = nano("https://$USERNAME:$PASSWORD@$USERNAME.cloudant.com");

account.request(function (err, body) {
  if (!err) {
    console.log(body);
  }
});

With Basic authentication, you pass along your credentials as part of every request by adding an Authorization header. The value is the authentication scheme (Basic), followed by the base-64 encoding of a string created by concatenating your username, the : character, and your password. However, most HTTP libraries do this encoding for you.

Cookie authentication requires you to supply a valid username and password once, at the start of a series of tasks (the session). The response includes a cookie, generated by the server, that confirms you have successfully authenticated. Once created, you send the cookie with all requests that require you to be authenticated. The presence of a valid cookie is sufficient to ensure that your call request is processed rather than rejected immediately as unauthenticated. You can use the cookie until it expires. Logging out causes the cookie to expire immediately.

Method Path Description Headers Form Parameters
POST /_session Do cookie based user login Content-Type: application/x-www-form-urlencoded name, password
GET /_session Returns cookie based login user information AuthSession cookie returned by POST request
DELETE /_session Logout cookie based user AuthSession cookie returned by POST request

Request a cookie

POST /_session HTTP/1.1
Content-Length: 32
Content-Type: application/x-www-form-urlencoded
Accept: */*

name=YourUserName&password=YourPassword
curl https://$USERNAME.cloudant.com/_session \
     -X POST \
     -c /path/to/cookiefile
     -d "name=$USERNAME&password=$PASSWORD"
import cloudant

account = cloudant.Account(USERNAME)
login = account.login(USERNAME, PASSWORD)
print login.status_code
# 200
logout = account.logout()
print logout.status_code
# 200
all_dbs = account.all_dbs()
print all_dbs.status_code
# 401
var nano = require('nano');
var cloudant = nano("https://"+$USERNAME+".cloudant.com");
var cookies = {}

cloudant.auth($USERNAME, $PASSWORD, function (err, body, headers) {
  if (!err) {
    cookies[$USERNAME] = headers['set-cookie'];
    cloudant = nano({
      url: "https://"+$USERNAME+".cloudant.com",
      cookie: cookies[$USERNAME] 
    });

    // ping to ensure we're logged in
    cloudant.request({
      path: 'test_porter'
    }, function (err, body, headers) {
      if (!err) {
        console.log(body, headers);
      }
    }); 
  }
});

With Cookie authentication, you use your credentials to acquire a cookie. Do this by sending a POST request to /_session.

Reply to request for a cookie

200 OK
Cache-Control: must-revalidate
Content-Length: 42
Content-Type: text/plain; charset=UTF-8
Date: Mon, 04 Mar 2013 14:06:11 GMT
server: CouchDB/1.0.2 (Erlang OTP/R14B)
Set-Cookie: AuthSession="a2ltc3RlYmVsOjUxMzRBQTUzOtiY2_IDUIdsTJEVNEjObAbyhrgz"; Expires=Tue, 05 Mar 2013 14:06:11 GMT; Max-Age=86400; Path=/; HttpOnly; Version=1
x-couch-request-id: a638431d
{
  "ok": true,
  "name": "kimstebel",
  "roles": []
}

If your credentials are valid, the response contains a cookie which remains active for twenty-four hours.

Example request for cookie information:

GET /_session HTTP/1.1
Cookie: AuthSession="a2ltc3RlYmVsOjUxMzRBQTUzOtiY2_IDUIdsTJEVNEjObAbyhrgz"; Expires=Tue, 05 Mar 2013 14:06:11 GMT; Max-Age=86400; Path=/; HttpOnly; Version=1
Accept: application/json
curl https://$USERNAME.cloudant.com/_session \
     -X GET \
     -b /path/to/cookiefile

When a cookie has been set, information about the logged in user can be retrieved with a GET request.

Example response to request for cookie information.

{
  "ok": true,
  "info": {
    "authentication_db": "_users",
    "authentication_handlers": ["cookie", "default"],
    "authenticated":"cookie"
  },
  "userCtx": {
    "name": "username",
    "roles": ["_admin","_reader","_writer"]
  }
}

The response contains the username, the user’s roles and which authentication mechanism was used.

Example cookie DELETE request:

DELETE /_session HTTP/1.1
Cookie: AuthSession="a2ltc3RlYmVsOjUxMzRBQTUzOtiY2_IDUIdsTJEVNEjObAbyhrgz"; Expires=Tue, 05 Mar 2013 14:06:11 GMT; Max-Age=86400; Path=/; HttpOnly; Version=1
Accept: application/json
curl https://$USERNAME.cloudant.com/_session \
     -X DELETE \
     -b /path/to/cookiefile

You can end the session by sending a DELETE request to the same URL used to create the cookie. The DELETE request must include the cookie you wish to delete.

Example response to cookie DELETE request:

200 OK
Cache-Control: must-revalidate
Content-Length: 12
Content-Type: application/json
Date: Mon, 04 Mar 2013 14:06:12 GMT
server: CouchDB/1.0.2 (Erlang OTP/R14B)
Set-Cookie: AuthSession=""; Expires=Fri, 02 Jan 1970 00:00:00 GMT; Max-Age=0; Path=/; HttpOnly; Version=1
x-couch-request-id: e02e0333
{
  "ok": true
}

The response confirms deletion of the session and sets the AuthSession Cookie to "".

Authorization

When you have authenticated, the next test is to decide whether you are permitted to perform certain tasks. This is called authorization.

Roles

Role Description
_reader Gives the user permission to read documents from the database.
_writer Gives the user permission to create and modify documents in the database.
_admin Gives the user all permissions, including setting permissions.
_replicator Gives the user permission to replicate a database, including creating checkpoints.
_db_updates Gives the user permission to use the global changes feed.
_design Gives the user access to views and design documents.
_shards Gives the user access to the /$DB/_shards endpoint.
_security Gives the user access to the /$DB/_security endpoint, letting them change roles of users.
_search_analyze Gives the user access to the /_search_analyze endpoint

The credentials you use to log in to the dashboard automatically have _admin permissions to all databases you create. Everyone and everything else, from users you share databases with to API keys you create, must be given a permission level explicitly.

Viewing Permissions

Example request to determine permissions:

GET /_api/v2/db/$DATABASE/_security HTTP/1.1
curl https://$USERNAME.cloudant.com/_api/v2/db/$DATABASE/_security \
     -u $USERNAME
var nano = require('nano');
var account = nano("https://"+$USERNAME+":"+$PASSWORD+"@"+$USERNAME+".cloudant.com");

account.request({
  db: $DATABASE,
  path: '_security'
}, function (err, body, headers) {
  if (!err) {
    console.log(body);
  }
});

To see who has permissions to read, write, and manage the database, make a GET request against https://$USERNAME.cloudant.com/$DB/_security.

Example response:

{
  "cloudant": {
    "antsellseadespecteposene": [
      "_reader",
      "_writer",
      "_admin"
    ],
    "garbados": [
      "_reader",
      "_writer",
      "_admin"
    ],
    "nobody": [
      "_reader"
    ]
  },
  "_id": "_security"
}

The cloudant field in the response object contains an object with keys that are the usernames that have permission to interact with the database. The nobody username indicates what rights are available to unauthenticated users – that is, any request made without authentication credentials. In the example response, for instance, nobody has _reader permissions, making the database publicly readable.

Modifying Permissions

Modification request:

PUT /_api/v2/db/$DATABASE/_security HTTP/1.1
Content-Type: application/json
curl https://$USERNAME:$PASSWORD@$USERNAME.cloudant.com/_api/v2/db/$DATABASE/_security \
     -X PUT \
     -H "Content-Type: application/json" \
     -d "$JSON"
var nano = require('nano');
var account = nano("https://"+$USERNAME+":"+$PASSWORD+"@"+$USERNAME+".cloudant.com");

account.request({
  db: $DATABASE,
  path: '_security',
  method: 'PUT',
  body: '$JSON'
}, function (err, body, headers) {
  if (!err) {
    console.log(body);
  }
});
{
  "cloudant": {
    "antsellseadespecteposene": [
      "_reader",
      "_writer",
      "_admin"
    ],
    "garbados": [
      "_reader",
      "_writer",
      "_admin"
    ],
    "nobody": [
      "_reader"
    ]
  }
}

To modify who has permissions to read, write, and manage a database, make a PUT request against https://$USERNAME.cloudant.com/_api/v2/db/$DB/_security. To see what roles you can assign, see Roles.

The request object’s cloudant field contains an object whose keys are usernames with permissions to interact with the database. The nobody username indicates what rights are available to unauthenticated users – that is, anybody. In the example request, for instance, nobody has _reader permissions, making the database publicly readable.

Example response:

{
  "ok" : true
}

The response tells you whether the update has been successful.

Creating API Keys

Example request to create an API key:

POST /api/generate_api_key HTTP/1.1
Host: cloudant.com
curl -X POST https://$USERNAME:$PASSWORD@cloudant.com/api/generate_api_key
var nano = require('nano');
var account = nano("https://$USERNAME:$PASSWORD@cloudant.com");

account.request({
  db: 'api',
  path: 'generate_api_ket',
  method: 'POST'
}, function (err, body) {
  if (!err) {
    console.log(body);
  }
});

API keys allow you to give access to a person or application without having to create a new Cloudant account. An API key consists of a randomly generated username and password. The key is given the desired access permissions. Once generated, the API key can be used in the same way as a normal user account, for example by granting read, write, or admin access permissions.

To generate an API key, use https://cloudant.com/api/generate_api_key. The created API key has no permissions to anything by default, and must be given permissions explicitly.

Response body:

{
  "password": "generatedPassword",
  "ok": true,
  "key": "generatedKey"
}

The response contains the generated key and password.

CORS

Cross-origin resource sharing (CORS) is a mechanism that allows resources such as JSON documents in a Cloudant database to be requested from Javascript running on a website loaded from another domain. These “cross-domain” requests would normally be forbidden by web browsers, due to the same origin security policy.

CORS defines a way in which the browser and the server interact to determine whether or not to allow the request. For Cloudant, there are two use cases in which CORS might be a good solution.

  1. You have a website on https://www.example.com and you want scripts on this website to be able to access data from https://example.cloudant.com. To do this, add https://www.example.com to your list of allowed origins. The effect is that scripts loaded from this domain are then allowed to make AJAX requests to your Cloudant databases. By using HTTP auth with CORS requests, users of your application are able to access their database only.
  2. You want to allow third parties access to your your database. An example might be where you have a database that contains product information, and you want to give sales partners access to the information from Javascript running on their own domain. To do this, add their domain to your list of allowed origins. The effect is that scripts running on their website are able to access your Cloudant database.

Browser support

CORS is supported by all current versions of commonly used browsers.

Security

Storing sensitive data in databases that can be accessed using CORS is a potential security risk. When you place a domain in the list of allowed origins, you are trusting any of the Javascript from the domain. If the web application running on the domain is running malicious code or has security vulnerabilities, sensitive data in your database might be exposed.

In addition, allowing scripts to be loaded using HTTP rather than HTTPS, and then accessing data using CORS, introduces the risk that a man in the middle attack might modify the scripts.

To reduce the risk:

Configuration endpoints

Method Path Description
GET /_api/v2/user/config/cors Returns the current CORS configuration
PUT /_api/v2/user/config/cors Changes the CORS configuration

JSON format

Setting the CORS configuration

Example request

PUT /_api/v2/user/config/cors HTTP/1.1
Host: $USERNAME.cloudant.com
Content-Type: application/json
curl https://$USERNAME:$PASSWORD@$USERNAME.cloudant.com/_api/v2/user/config/cors -H 'Content-Type: application/json' -X PUT -T cors.json
# where cors.json is a file with the following JSON document:
{
    "enable_cors": true,
    "allow_credentials": true,
    "origins": [
         "https://example.com",
         "https://www.example.com"
     ]
}

PUTting a json document with the example structure to /_api/v2/user/config/cors sets the CORS configuration. The configuration applies to all databases and all account level endpoints in your account.

Example response

{ "ok": true }

The response tells you whether the configuration has been updated successfully.

Reading the CORS configuration

Example request

GET /_api/v2/user/config/cors HTTP/1.1
Host: username.cloudant.com
curl https://$USERNAME:$PASSWORD@$USERNAME.cloudant.com/_api/v2/user/config/cors

GETting /_api/v2/user/config/cors

Example response

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 178
{
    "enable_cors": true,
    "allow_credentials": true,
    "origins": [
        "https://example.com",
        "https://www.example.com"
    ]
}

… returns the CORS config in a JSON document.

Databases

Cloudant databases contain JSON objects. These JSON objects are called documents. All documents must be contained in a database.

You interact with Cloudant databases and documents using API commands, as this overview explains:

Create

Create a database

PUT /$DATABASE HTTP/1.1
HOST: $ACCOUNT.cloudant.com
curl https://$USERNAME:$PASSWORD@$ACCOUNT.cloudant.com/$DATABASE -X PUT
var nano = require('nano');
var account = nano("https://"+$USERNAME+":"+$PASSWORD+"@"+$USERNAME+".cloudant.com");

account.db.create($DATABASE, function (err, body, headers) {
  if (!err) {
    console.log('database created!');
  }
});

To create a database, make a PUT request to https://$USERNAME.cloudant.com/$DATABASE.

The database name must start with a lowercase letter and contain only the following characters:

Query Parameters

Create a database with non-default values for n and q

curl -X PUT 'http://$USERNAME:$PASSWORD@$USERNAME.cloudant.com/$DATABASE?n=2&q=32'
PUT /$DATABASE?n=2&q=32 HTTP/1.1
HOST: $ACCOUNT.cloudant.com

There are two configuration parameters that control the sharding topology of a database. The defaults are specified in the server configuration and may be overridden at database creation time on dedicated database clusters. N specifies the number of replicas of each document, while Q fixes the number of partitions of the database. On multi-tenant clusters, the default can not be overwritten.

Parameter Description Default
n number of replicas of each document 3
q number of partitions of the database 4

Response

Response for successful creation:

HTTP/1.1 201 Created

{
  "ok": true
}

If creation succeeds, you get a 201 or 202 response. In case of an error, the HTTP status code tells you what went wrong.

Code Description
201 Database created successfully
202 The database has been successfully created on some nodes, but the number of nodes is less than the write quorum.
403 Invalid database name.
412 Database aleady exists.

Read

Create a database

GET /$DATABASE HTTP/1.1
curl https://$USERNAME.cloudant.com/$DATABASE \
     -u $USERNAME
var nano = require('nano');
var account = nano("https://"+$USERNAME+":"+$PASSWORD+"@"+$USERNAME+".cloudant.com");

account.db.get($DATABASE, function (err, body, headers) {
  if (!err) {
    console.log(body);
  }
});

Making a GET request against https://$USERNAME.cloudant.com/$DATABASE returns details about the database, such as how many documents it contains.

Example response:

{
  "update_seq": "0-g1AAAADneJzLYWBgYMlgTmFQSElKzi9KdUhJMtbLTS3KLElMT9VLzskvTUnMK9HLSy3JAapkSmRIsv___39WIgOqHkM8epIcgGRSPTZt-KzKYwGSDA1ACqhzP0k2QrQegGgF2ZoFAGdBTTo",
  "db_name": "db",
  "purge_seq": 0,
  "other": {
    "data_size": 0
  },
  "doc_del_count": 0,
  "doc_count": 0,
  "disk_size": 316,
  "disk_format_version": 5,
  "compact_running": false,
  "instance_start_time": "0"
}

The elements of the returned structure are shown in the table below:

Field Description
compact_running Set to true if the database compaction routine is operating on this database.
db_name The name of the database.
disk_format_version The version of the physical format used for the data when it is stored on disk.
disk_size Size in bytes of the data as stored on the disk. Views indexes are not included in the calculation.
doc_count A count of the documents in the specified database.
doc_del_count Number of deleted documents
instance_start_time Always 0.
purge_seq The number of purge operations on the database.
update_seq An opaque string describing the state of the database. It should not be relied on for counting the number of updates.
other Json object containing a data_size field.

Get Databases

Get all databases

GET /_all_dbs HTTP/1.1
curl https://$USERNAME.cloudant.com/_all_dbs \
     -u $USERNAME
var nano = require('nano');
var account = nano("https://"+$USERNAME+":"+$PASSWORD+"@"+$USERNAME+".cloudant.com");

account.db.list(function (err, body, headers) {
  if (!err) {
    console.log(body);
  }
});

To list all the databases in an account, make a GET request against https://$USERNAME.cloudant.com/_all_dbs.

Example response:

[
   "_users",
   "contacts",
   "docs",
   "invoices",
   "locations"
]

The response is an array with all database names.

Get Documents

Getting all documents in a database

GET /_all_docs HTTP/1.1
curl https://%USERNAME:$PASSWORD@$USERNAME.cloudant.com/$DATABASE/_all_docs
var nano = require('nano');
var account = nano("https://"+$USERNAME+":"+$PASSWORD+"@"+$USERNAME+".cloudant.com");
var db = account.use($DATABASE);

db.list(function (err, body, headers) {
  if (!err) {
    console.log(body);
  }
});

To list all the documents in a database, make a GET request against https://$USERNAME.cloudant.com/$DATABASE/_all_docs.

The method accepts these query arguments:

Argument Description Optional Type Default
descending Return the documents in descending by key order yes boolean false
endkey Stop returning records when the specified key is reached yes string
include_docs Include the full content of the documents in the return yes boolean false
inclusive_end Include rows whose key equals the endkey yes boolean true
key Return only documents that match the specified key yes string
limit Limit the number of the returned documents to the specified number yes numeric
skip Skip this number of records before starting to return the results yes numeric 0
startkey Return records starting with the specified key yes string

Example response:

{
  "total_rows": 3,
  "offset": 0,
  "rows": [{
    "id": "5a049246-179f-42ad-87ac-8f080426c17c",
    "key": "5a049246-179f-42ad-87ac-8f080426c17c",
    "value": {
      "rev": "2-9d5401898196997853b5ac4163857a29"
    }
  }, {
    "id": "96f898f0-f6ff-4a9b-aac4-503992f31b01",
    "key": "96f898f0-f6ff-4a9b-aac4-503992f31b01",
    "value": {
      "rev": "2-ff7b85665c4c297838963c80ecf481a3"
    }
  }, {
    "id": "d1f61e66-7708-4da6-aa05-7cbc33b44b7e",
    "key": "d1f61e66-7708-4da6-aa05-7cbc33b44b7e",
    "value": {
      "rev": "2-cbdef49ef3ddc127eff86350844a6108"
    }
  }]
}

The response is a JSON object containing all documents in the database matching the parameters. The following table describes the meaning of the individual fields:

Field Description Type
offset Offset where the document list started numeric
rows Array of document objects array
total_rows Number of documents in the database/view matching the parameters of the query numeric
update_seq Current update sequence for the database string

Get Changes

Example request to get list of changes made to documents in a database:

GET /$DATABASE/_changes HTTP/1.1
curl https://$USERNAME.cloudant.com/$DATABASE/_changes \
     -u $USERNAME
var nano = require('nano');
var account = nano("https://"+$USERNAME+":"+$PASSWORD+"@"+$USERNAME+".cloudant.com");

account.db.changes($DATABASE, function (err, body, headers) {
  if (!err) {
    console.log(body);
  }
});

Example response:

{
  "results": [{
    "seq": "1-g1AAAAI9eJyV0EsKwjAUBdD4Ad2FdQMlMW3TjOxONF9KqS1oHDjSnehOdCe6k5oQsNZBqZP3HiEcLrcEAMzziQSB5KLeq0zyJDTqYE4QJqEo66NklQkrZUr7c8wAXzRNU-T22tmHGVMUapR2Bdwj8MBOvu4gscQyUtghyw-CYJ-SOWXTUSJMkKQ_UWgfsnXIuYOkhCCN6PBGqqmd4GKXda4OGvk0VCcCweHFeOjmoXubiEREIyb-KMdLDy89W4nTVGkqhhfkoZeHvkrimMJYrYo31bKsIg",
    "id": "foo",
    "changes": [{
      "rev": "1-967a00dff5e02add41819138abb3284d"
    }]
  }],
  "last_seq": "1-g1AAAAI9eJyV0EsKwjAUBdD4Ad2FdQMlMW3TjOxONF9KqS1oHDjSnehOdCe6k5oQsNZBqZP3HiEcLrcEAMzziQSB5KLeq0zyJDTqYE4QJqEo66NklQkrZUr7c8wAXzRNU-T22tmHGVMUapR2Bdwj8MBOvu4gscQyUtghyw-CYJ-SOWXTUSJMkKQ_UWgfsnXIuYOkhCCN6PBGqqmd4GKXda4OGvk0VCcCweHFeOjmoXubiEREIyb-KMdLDy89W4nTVGkqhhfkoZeHvkrimMJYrYo31bKsIg",
  "pending": 0
}

Example response, continuous changes feed:

{
  "seq": "1-g1AAAAI7eJyN0EsOgjAQBuD6SPQWcgLSIm1xJTdRph1CCEKiuHClN9Gb6E30JlisCXaDbGYmk8mXyV8QQubZRBNPg6r2GGsI_BoP9YlS4auiOuqkrP0S68JcjhMCi6Zp8sxMO7OYISgUK3AF1iOAZyqsv8jog4Q6YIxyF4n6kLhFNs4nIQ-kUtJFwj5k2yJnB0lxSbkIhgdSTk0lF9OMc-0goCpikg7PxUI3C907KMKUM9AuJP9CDws9O0ghAtc4PB8LvSz0k5HgKTCU-RtU1qyw",
  "id": "2documentation22d01513-c30f-417b-8c27-56b3c0de12ac",
  "changes": [{
    "rev": "1-967a00dff5e02add41819138abb3284d"
  }]
}
{
  "seq": "2-g1AAAAI7eJyN0E0OgjAQBeD6k-gt5ASkRdriSm6iTDuEEIREceFKb6I30ZvoTbBYE-wG2cxMmubLyysIIfNsoomnQVV7jDUEfo2H-kSp8FVRHXVS1n6JdWF-jhMCi6Zp8sxcO_MwQ1AoVuAKrEcAz0xYf5HRBwl1wBjlLhL1IXGLbJwkIQ-kUtJFwj5k2yJnJ0mKS8pFMLyQcmomuZhlnGuXBqiKmKTDe7HQzUL3Doow5Qy0C8m_0MNCzw5SiMA1Du_HQi8L_RQteAoMZf4GVgissQ",
  "id": "1documentation22d01513-c30f-417b-8c27-56b3c0de12ac",
  "changes": [{
    "rev": "1-967a00dff5e02add41819138abb3284d"
  }]
}
{
  "seq": "3-g1AAAAI7eJyN0EsOgjAQBuD6SPQWcgLSIqW4kpso0w4hBCFRXLjSm-hN9CZ6EyyUBLtBNjOTyeTL5M8JIct0poijQJZHjBR4boWn6kJp4Mq8PKu4qNwCq1xfTmMCq7qus1RPB71YIEgMNmALbEAAR1fYdsikRXzlMUa5jYRDSNQgO-sTn3tCSmEj_hCyb5Brh0xbJME15YE3PpBiriu56aade_8NUBkyQcfnYqCHgZ49FGLCGSgbEn-hl4HePSQRgSscn4-BPgb6CTrgCTAU2RdXOqyy",
  "id": "1documentation22d01513-c30f-417b-8c27-56b3c0de12ac",
  "changes": [{
    "rev": "2-eec205a9d413992850a6e32678485900"
  }],
  "deleted": true
}
{
  "seq": "4-g1AAAAI7eJyN0EEOgjAQBdAGTfQWcgLSIm1xJTdRph1CCEKiuHClN9Gb6E30JlisCXaDbGYmTfPy80tCyDyfaOJrUPUeEw1h0OChOVEqAlXWR51WTVBhU5qfXkpg0bZtkZtrZx5mCArFClyBDQjgmwnrL-J9kEiHjFHuIvEQknTIxkkS8VAqJV0kGkK2HXJ2kmS4pFyE4wuppmaSi1nGufZpgKqYSTq-FwvdLHTvoRgzzkC7kPwLPSz07CGFCFzj-H4s9LLQT9GCZ8BQFm9Y9qyz",
  "id": "2documentation22d01513-c30f-417b-8c27-56b3c0de12ac",
  "changes": [{
    "rev": "2-eec205a9d413992850a6e32678485900"
  }],
  "deleted": true
}

Making a GET request against https://$USERNAME.cloudant.com/$DATABASE/_changes returns a list of changes made to documents in the database, including insertions, updates, and deletions. This log might not be in chronological order.

_changes accepts these query arguments:

Argument Description Supported Values Default
descending Return the changes in sequential order boolean false
feed Type of feed "continuous", "longpoll", "normal" "normal"
filter Name of filter function from a design document to get updates string no filter
heartbeat Time in milliseconds after which an empty line is sent during longpoll or continuous if there have been no changes any positive number 60000
include_docs Include the document with the result boolean false
limit Maximum number of rows to return any non-negative number none
since Start the results from changes after the specified sequence number. If since is 0 (the default), the request will return all changes. string 0
style Specifies how many revisions are returned in the changes array. The default, main_only, only returns the current “winning” revision; all_docs returns all leaf revisions, including conflicts and deleted former conflicts. main_only, all_docs main_only
timeout Number of milliseconds to wait for data before terminating the response. If heartbeat supersedes timeout if both are supplied. any positive number

All arguments are optional.

The feed argument changes how Cloudant sends the response. By default, changes feed in entirety and the connection closes.

If you set feed=longpoll, requests to the server remain open until changes are reported. This can help monitor changes specifically instead of continuously.

If you set feed=continuous, new changes send without closing the connection. In this mode the format of changes accomodates the continuous nature while ensuring validity of the JSON output.

The filter parameter designates a pre-defined function to filter the changes feed.

Delete

Example request to delete a Cloudant database:

DELETE /$DATABASE HTTP/1.1
Host: $USERNAME.cloudant.com
curl https://$USERNAME.cloudant.com/$DATABASE \
     -X DELETE \
     -u $USERNAME
var nano = require('nano');
var account = nano("https://"+$USERNAME+":"+$PASSWORD+"@"+$USERNAME+".cloudant.com");

account.db.destroy($DATABASE, function (err, body, headers) {
  if (!err) {
    console.log(body);
  }
});

To delete a databases and its contents, make a DELETE request to https://$USERNAME.cloudant.com/$DATABASE.

Example response:

{
  "ok": true
}

The response confirms successful deletion of the database or describes any errors that occured, i.e. if you try to delete a database that does not exist.

Documents

Documents are JSON objects. Documents are containers for your data, and are the basis of the Cloudant database.

All documents must have two fields: a unique _id field, and a _rev field. The _id field is either created by you, or generated automatically as a UUID by Cloudant. The _rev field is a revision number, and is essential to Cloudant’s replication protocol. In addition to these two mandatory fields, documents can contain any other content expressed using JSON.

Create

Creating a document:

POST /$DATABASE HTTP/1.1
Content-Type: application/json
curl https://$USERNAME:$PASSWORD@$USERNAME.cloudant.com/$DATABASE \
     -X POST \
     -H "Content-Type: application/json" \
     -d "$JSON"
var nano = require('nano');
var account = nano("https://"+$USERNAME+":"+$PASSWORD+"@"+$USERNAME+".cloudant.com");
var db = account.use($DATABASE);

db.insert($JSON, function (err, body, headers) {
  if (!err) {
    console.log(body);
  }
});
{
  "_id": "apple",
  "item": "Malus domestica",
  "prices": {
    "Fresh Mart": 1.59,
    "Price Max": 5.99,
    "Apples Express": 0.79
  }
}

To create a document, make a POST request with the document’s JSON content to https://$USERNAME.cloudant.com/$DATABASE.

Example response:

{
  "ok":true,
  "id":"apple",
  "rev":"1-2902191555"
}

The response is a JSON document containing the ID of the created document, the revision string, and "ok": true. If you did not provide an _id field, Cloudant generates one automatically as a UUID. If creation of the document failed, the response contains a description of the error.

Read

Reading a document:

GET /$DATABASE/$DOCUMENT_ID HTTP/1.1
curl https://$USERNAME:$PASSWORD@$USERNAME.cloudant.com/$DATABASE/$DOCUMENT_ID
var nano = require('nano');
var account = nano("https://"+$USERNAME+":"+$PASSWORD+"@"+$USERNAME+".cloudant.com");
var db = account.use($DATABASE);

db.get($JSON._id, function (err, body, headers) {
  if (!err) {
    console.log(body);
  }
});

To retrieve a document, make a GET request to https://$USERNAME.cloudant.com/$DATABASE/$DOCUMENT_ID. If you do not know the _id for a particular document, you can query the database for all documents.

Example response:

{
  "_id": "apple",
  "_rev": "1-2902191555",
  "item": "Malus domestica",
  "prices": {
    "Fresh Mart": 1.59,
    "Price Max": 5.99,
    "Apples Express": 0.79
  }
}

The response contains the document you requested or a description of the error, if the document could not be retrieved.

Read Many

To fetch many documents at once, query the database.

Update

Updating a document

PUT /$DATABASE/$DOCUMENT_ID HTTP/1.1
// make sure $JSON contains the correct `_rev` value!
curl https://$USERNAME:$PASSWORD@$USERNAME.cloudant.com/$DATABASE/$DOCUMENT_ID \
     -X PUT \
     -H "Content-Type: application/json" \
     -d "$JSON"
var nano = require('nano');
var account = nano("https://"+$USERNAME+":"+$PASSWORD+"@"+$USERNAME+".cloudant.com");
var db = account.use($DATABASE);

// make sure $JSON contains the correct `_rev` value!
$JSON._rev = $REV;

db.insert($JSON, $JSON._id, function (err, body, headers) {
  if (!err) {
    console.log(body);
  }
});
{
  "_id": "apple",
  "_rev": "1-2902191555",
  "item": "Malus domestica",
  "prices": {
    "Fresh Mart": 1.59,
    "Price Max": 5.99,
    "Apples Express": 0.79,
    "Gentlefop's Shackmart": 0.49
  }
}

To update (or create) a document, make a PUT request with the updated JSON content and the latest _rev value (not needed for creating new documents) to https://$USERNAME.cloudant.com/$DATABASE/$DOCUMENT_ID.

Example response:

{
  "ok":true,
  "id":"apple",
  "rev":"2-9176459034"
}

The response contains the ID and the new revision of the document or an error message in case the update failed.

Delete

Delete request

DELETE /$DATABASE/$DOCUMENT_ID?rev=$REV HTTP/1.1
// make sure $JSON contains the correct `_rev` value!
curl https://$USERNAME:$PASSWORD@$USERNAME.cloudant.com/$DATABASE/$DOCUMENT_ID?rev=$REV -X DELETE
var nano = require('nano');
var account = nano("https://"+$USERNAME+":"+$PASSWORD+"@"+$USERNAME+".cloudant.com");
var db = account.use($DATABASE);

// make sure $JSON contains the correct `_rev` value!
db.destroy($JSON._id, $REV, function (err, body, headers) {
  if (!err) {
    console.log(body);
  }
});

To delete a document, make a DELETE request with the document’s latest _rev in the querystring, to https://$USERNAME.cloudant.com/$DATABASE/$DOCUMENT_ID.

Deletion response:

{
  "id" : "apple",
  "ok" : true,
  "rev" : "3-2719fd4118"
}

The response contains the ID and the new revision of the document or an error message in case the update failed.

Bulk Operations

The bulk document API allows you to create and update multiple documents at the same time within a single request. The basic operation is similar to creating or updating a single document, except that you batch the document structure and information. When creating new documents the document ID is optional. For updating existing documents, you must provide the document ID, revision information, and new document values.

Request Body

Request to update/create/delete multiple documents:

POST /$DATABASE/_bulk_docs HTTP/1.1
Content-Type: application/json
curl https://$USERNAME:$PASSWORD@$USERNAME.cloudant.com/$DATABASE/_bulk_docs -X POST -H "Content-Type: application/json" -d "$JSON"
var nano = require('nano');
var account = nano("https://$USERNAME:$PASSWORD@$USERNAME.cloudant.com");
var db = account.use($DATABASE);

db.bulk($JSON, function (err, body) {
  if (!err) {
    console.log(body);
  }
});
{
  "docs": [
    {
      "name": "Nicholas",
      "age": 45,
      "gender": "female",
      "_id": "96f898f0-f6ff-4a9b-aac4-503992f31b01",
      "_rev": "1-54dd23d6a630d0d75c2c5d4ef894454e"
    },
    {
      "name": "Taylor",
      "age": 50,
      "gender": "female"
    },
    {
      "_id": "d1f61e66-7708-4da6-aa05-7cbc33b44b7e",
      "_rev": "1-a2b6e5dac4e0447e7049c8c540b309d6",
      "_deleted": true
    }
  ]
}

For both inserts and updates the basic structure of the JSON document in the request is the same:

Field Description Type Optional
docs Bulk Documents Document array of objects no

Object in docs array

Field Description Type Optional
_id Document ID string optional only for new documents
_rev Document revision string mandatory for updates and deletes, not used for new documents
_deleted Whether the document should be deleted boolean yes

Response

Example response:

[{
  "id": "96f898f0-f6ff-4a9b-aac4-503992f31b01",
  "rev": "2-ff7b85665c4c297838963c80ecf481a3"
}, {
  "id": "5a049246-179f-42ad-87ac-8f080426c17c",
  "rev": "2-9d5401898196997853b5ac4163857a29"
}, {
  "id": "d1f61e66-7708-4da6-aa05-7cbc33b44b7e",
  "rev": "2-cbdef49ef3ddc127eff86350844a6108"
}]

The HTTP status code tells you whether the request was fully or partially successful. In the response body, you get an array with detailed information for each document in the request.

Code Description
201 All documents have been created or updated.
202 For at least one document, the write quorum (specified by w) has not been met.

Inserting Documents in Bulk

Example bulk insert of three documents:

{
  "docs": [{
    "name": "Nicholas",
    "age": 45,
    "gender": "male",
    "_id": "96f898f0-f6ff-4a9b-aac4-503992f31b01",
    "_attachments": {

    }
  }, {
    "name": "Taylor",
    "age": 50,
    "gender": "male",
    "_id": "5a049246-179f-42ad-87ac-8f080426c17c",
    "_attachments": {

    }
  }, {
    "name": "Owen",
    "age": 51,
    "gender": "male",
    "_id": "d1f61e66-7708-4da6-aa05-7cbc33b44b7e",
    "_attachments": {

    }
  }]
}

To insert documents in bulk into a database you need to supply a JSON structure with the array of documents that you want to add to the database. You can either include a document ID for each document, or allow the document ID to be automatically generated.

Example response header after bulk insert of three documents:

201 Created
Cache-Control: must-revalidate
Content-Length: 269
Content-Type: application/json
Date: Mon, 04 Mar 2013 14:06:20 GMT
server: CouchDB/1.0.2 (Erlang OTP/R14B)
x-couch-request-id: e8ff64d5

Example response content after bulk insert of three documents:

    [{
      "id": "96f898f0-f6ff-4a9b-aac4-503992f31b01",
      "rev": "1-54dd23d6a630d0d75c2c5d4ef894454e"
    }, {
      "id": "5a049246-179f-42ad-87ac-8f080426c17c",
      "rev": "1-0cde94a828df5cdc0943a10f3f36e7e5"
    }, {
      "id": "d1f61e66-7708-4da6-aa05-7cbc33b44b7e",
      "rev": "1-a2b6e5dac4e0447e7049c8c540b309d6"
    }]

The return code from a successful bulk insertion is 201, with the content of the returned structure indicating specific success or otherwise messages on a per-document basis.

The return structure from the example contains a list of the documents created, including their revision and ID values.

The content and structure of the returned JSON depends on the transaction semantics being used for the bulk update; see Bulk Documents Transaction Semantics for more information. Conflicts and validation errors when updating documents in bulk must be handled separately; see Bulk Document Validation and Conflict Errors.

Updating Documents in Bulk

Example request to perform bulk update:

POST /test/_bulk_docs HTTP/1.1
Accept: application/json

Example JSON to bulk update documents:

{
  "docs": [{
    "name": "Nicholas",
    "age": 45,
    "gender": "female",
    "_id": "96f898f0-f6ff-4a9b-aac4-503992f31b01",
    "_attachments": {

    },
    "_rev": "1-54dd23d6a630d0d75c2c5d4ef894454e"
  }, {
    "name": "Taylor",
    "age": 50,
    "gender": "female",
    "_id": "5a049246-179f-42ad-87ac-8f080426c17c",
    "_attachments": {

    },
    "_rev": "1-0cde94a828df5cdc0943a10f3f36e7e5"
  }, {
    "name": "Owen",
    "age": 51,
    "gender": "female",
    "_id": "d1f61e66-7708-4da6-aa05-7cbc33b44b7e",
    "_attachments": {

    },
    "_rev": "1-a2b6e5dac4e0447e7049c8c540b309d6"
  }]
}

The bulk document update procedure is similar to the insertion procedure, except that you must specify the document ID and current revision for every document in the bulk update JSON string.

Example JSON structure returned after bulk update:

[{
  "id": "96f898f0-f6ff-4a9b-aac4-503992f31b01",
  "rev": "2-ff7b85665c4c297838963c80ecf481a3"
}, {
  "id": "5a049246-179f-42ad-87ac-8f080426c17c",
  "rev": "2-9d5401898196997853b5ac4163857a29"
}, {
  "id": "d1f61e66-7708-4da6-aa05-7cbc33b44b7e",
  "rev": "2-cbdef49ef3ddc127eff86350844a6108"
}]

The return structure is the JSON of the updated documents, with the new revision and ID information.

You can optionally delete documents during a bulk update by adding the _deleted field with a value of true to each document ID/revision combination within the submitted JSON structure.

The return code from a successful bulk update is 201, with the content of the returned structure indicating specific success or otherwise messages on a per-document basis.

The content and structure of the returned JSON depends on the transaction semantics being used for the bulk update; see Bulk Documents Transaction Semantics for more information. Conflicts and validation errors when updating documents in bulk must be handled separately; see Bulk Document Validation and Conflict Errors.

Bulk Documents Transaction Semantics

Response with errors

[
   {
      "id" : "FishStew",
      "error" : "conflict",
      "reason" : "Document update conflict."
   },
   {
      "id" : "LambStew",
      "error" : "conflict",
      "reason" : "Document update conflict."
   },
   {
      "id" : "7f7638c86173eb440b8890839ff35433",
      "error" : "conflict",
      "reason" : "Document update conflict."
   }
]

Cloudant only guarantees that some of the documents are saved if your request yields a 202 response. The response contains the list of documents successfully inserted or updated during the process.

The response structure indicates whether the document was updated successfully. It does this by supplying the new _rev parameter, indicating that a new document revision was successfully created.

If the update failed, then you get an error of type conflict. In this case, no new revision has been created. You must submit the document update with the correct revision tag, to update the document.

Bulk Document Validation and Conflict Errors

The JSON returned by the _bulk_docs operation consists of an array of JSON structures, one for each document in the original submission. The returned JSON structure should be examined to ensure that all of the documents submitted in the original request were successfully added to the database.

The structure of the returned information is:

Field Description Type
docs [array] Bulk Documents Document array of objects

Fields of objects in docs array

Field Description Type
id Document ID string
error Error type string
reason Error string with extended reason string

When a document (or document revision) is not correctly committed to the database because of an error, you should check the error field to determine error type and course of action. The error is one of conflict or forbidden.

conflict

The document as submitted is in conflict. If you used the default bulk transaction mode, then the new revision was not created. You must re-submit the document to the database.

Conflict resolution of documents added using the bulk docs interface is identical to the resolution procedures used when resolving conflict errors during replication.

forbidden

Example javascript to produce forbidden error as part of a validation function:

throw({forbidden: 'invalid recipe ingredient'});

Resulting error message from the validation function:

{
   "id" : "7f7638c86173eb440b8890839ff35433",
   "error" : "forbidden",
   "reason" : "invalid recipe ingredient"
}

Entries with this error type indicate that the validation routine applied to the document during submission has returned an error.

Attachments

If you want to store data, use attachments. Attachments are Binary Large Object (BLOb) files contained within documents. The BLOb is stored in the _attachments component of the document. The BLOb includes data about the attachment name, the type of the attachment, and the actual content represented in BASE64 form. Examples of BLObs would be images and multimedia.

The content type corresponds to a MIME type. For example, if you want to attach a .jpg image file to a document, you would specify the attachment MIME type as image/jpeg.

Create / Update

Example instruction for creating or updating an attachment:

PUT /$DATABASE/$DOCUMENT_ID/$ATTACHMENT?rev=$REV HTTP/1.1
Content-Type: $$ATTACHMENT_MIME_TYPE
curl https://$USERNAME:$PASSWORD@$USERNAME.cloudant.com/$DATABASE/$DOCUMENT_ID/$ATTACHMENT?rev=$REV \
     -X PUT \
     -H "Content-Type: $ATTACHMENT_MIME_TYPE" \
     --data-binary @$ATTACHMENT_FILEPATH
var nano = require('nano');
var fs = require('fs');
var account = nano("https://$USERNAME:$PASSWORD@$USERNAME.cloudant.com");
var db = account.use($DATABASE);

fs.readFile($FILEPATH, function (err, data) {
  if (!err) {
    db.attachment.insert($DOCUMENT_ID, $ATTACHMENT, data, $ATTACHMENT_MIME_TYPE, { 
      rev: $REV
    }, function (err, body) {
      if (!err)
        console.log(body);
    });
  }
});

To create a new attachment at the same time as creating a new document, include the attachment as an ‘inline’ component of the JSON content.

To create a new attachment on an existing document, or to update an attachment on a document, make a PUT request with the document’s latest _rev to https://$USERNAME.cloudant.com/$DATABASE/$DOCUMENT_ID/$ATTACHMENT. The attachment’s content type must be specified using the Content-Type header. The $ATTACHMENT value is the name by which the attachment is associated with the document.

Example response:

{
  "id" : "FishStew",
  "ok" : true,
  "rev" : "9-247bb19a41bfd9bfdaf5ee6e2e05be74"
}

The response contains the document ID and the new document revision. Note that attachments do not have their own revisions. Instead, updating or creating an attachment changes the revision of the document it is attached to.

Read

Example instruction for reading an attachment:

GET /$DATABASE/$DOCUMENT_ID/$ATTACHMENT HTTP/1.1
curl https://$USERNAME.cloudant.com/$DATABASE/$DOCUMENT_ID/$ATTACHMENT \
     -u $USERNAME >blob_content.dat
# store the response content into a file for further processing.
var nano = require('nano');
var account = nano("https://$USERNAME:$PASSWORD@$USERNAME.cloudant.com");
var db = account.use($DATABASE);

db.attachment.get($DOCUMENT_ID, $FILENAME, function (err, body) {
  if (!err) {
    console.log(body);
  }
});

To retrieve an attachment, make a GET request to https://$USERNAME.cloudant.com/$DATABASE/$DOCUMENT_ID/$ATTACHMENT. The body of the response is the raw content of the attachment.

Delete

Example instruction for deleting an attachment:

DELETE /$DATABASE/$DOCUMENT_ID/$ATTACHMENT?rev=$REV HTTP/1.1
curl https://$USERNAME.cloudant.com/$DATABASE/$DOCUMENT_ID/$ATTACHMENT?rev=$REV \
     -u $USERNAME \
     -X DELETE
var nano = require('nano');
var account = nano("https://$USERNAME:$PASSWORD@$USERNAME.cloudant.com");
var db = account.use($DATABASE);

db.attachment.destroy($DOCUMENT_ID, $FILENAME, $REV, function (err, body) {
  if (!err) {
    console.log(body);
  }
});

To delete an attachment, make a DELETE request with the document’s latest _rev to https://$USERNAME.cloudant.com/$DATABASE/$DOCUMENT_ID/$ATTACHMENT. If you do not supply the latest _rev, the response is a 409 error.

Example response:

{
  "ok": true,
  "id": "DocID",
  "rev": "3-aedfb06537c1d77a087eb295571f7fc9"
}

If the deletion is successful, the response contains "ok": true, and the ID and new revision of the document.

Inline

Example JSON content that includes an inline attachment of a jpeg image:

{
  "_id":"document_with_attachment",
  "_attachments":
  {
    "name_of_attachment":
    {
      "content_type":"image/jpeg",
      "data": "iVBORw0KGgoAA... ...AASUVORK5CYII="
    }
  }
}

Inline attachments are attachments included as part of the JSON content.

Query

Cloudant Query is a declarative JSON querying syntax for Cloudant databases. Cloudant Query wraps several index types, starting with the Primary Index out-of-the-box. Cloudant Query indexes can also be built using MapReduce Views (where the index type is json), and Search Indexes (where the index type is text).

If you know exactly what data you want to look for, or you want to keep storage and processing requirements to a minimum, you can specify how the index is created, by making it of type json.

But for maximum possible flexibility when looking for data, you would typically create an index of type text.

Creating an index

You can create an index with one of two types:

Creating a “type=json” index

Example of creating a new index for the field called foo:

POST /db/_index HTTP/1.1
Content-Type: application/json
{
    "index": {
        "fields": ["foo"]
    },
    "name" : "foo-index",
    "type" : "json"
}

The returned JSON confirms the index has been created:

{
    "result": "created"
}

Creates a new index in the specified database using the information supplied in the request body.

Request Body
Return Codes
Code Description
200 Index has been created successfully or already existed
400 Bad request: the request body does not have the specified format

Creating a “type=text” index

Example index creation request

{
  "type": "text",
  "name": "my-index",
  "ddoc": "my-index-design-doc",
  "index": {
    "default_field": {
      "enabled": true,
      "analyzer": "german"
    }
    "selector": {}
    "fields": [
      {"name": "married", "type": "boolean"},
      {"name": "lastname", "type": "string"},
      {"name": "year-of-birth", "type": "number"}
    ]
  }
}

While it is generally recommended that you create a single text index with the default values, there are a few useful index attributes that can be modified.

Remember that for Full Text Indexes (FTIs), type should be set to text.

The name and ddoc attributes are for grouping indexes into design documents, and allowing you to refer to them by a custom string value. If no values are supplied for these fields, they are automatically populated with a hash value.

If you create multiple text indexes in a database, with the same ddoc value, you need to know at least the ddoc value as well as the name value. Creating multiple indexes with the same ddoc value places them into the same design document. Generally, you should put each text index into its own design document.

The index field

The index field contains settings specific to text indexes.

The default_field value affects how the index for handling the $text operator is created. In almost all cases this should be left enabled. Do this by setting the value to true, or simply not including the enabled field.

The analyzer key in the default_field can be used to choose how to analyze text included in the index. See the Cloudant Search documentation for alternative analyzers. You might choose to use an alternative analyzer when documents are indexed in languages other than English, or when you have other special requirements for the analyser such as matching email addresses.

The selector field

The selector field can be used to limit the index to a specific set of documents that match a query. It uses the same syntax used for selectors in queries. This can be used if your application requires different documents to be indexed in different ways, or if some documents should not be indexed at all. If you only need to distinguish documents by type, it is easier to use one index and add the type to the search query.

The fields array

The fields array contains a list of fields that should be indexed for each document. If you know that an index queries only on specific fields, then this field can be used to limit the size of the index. Each field must also specify a type to be indexed. The acceptable types are:

Query Parameters

Example using all available query parameters

{
  "selector": {
    "query": "here"
  },
  "fields": [
    "_id",
    "_rev",
    "foo",
    "bar"
  ],
  "sort": [
    {
      "bar:number": "asc"
    },
    {
      "foo:string": "asc"
    }
  ],
  "bookmark": "opaque string",
  "limit": 10,
  "skip": 0
}

The format of the selector field is as described in the selector syntax, with the exception of the new $text operator.

The $text operator is based on a Lucene search with a standard analyzer. This means the operator is not case sensitive, and matches on any words. However, the $text operator does not support full Lucene syntax, such as wildcards, fuzzy matches, or proximity detection. For more information on the available Lucene syntax, see Cloudant Search documentation. The $text operator applies to all strings found in the document. It is invalid to place this operator in the context of a field name.

The fields array is a list of fields that should be returned for each document. The provided field names can use dotted notation to access subfields.

Working with indexes

Cloudant endpoints can be used to create, list, update, and delete indexes in a database, and to query data using these indexes.

A list of the available methods and endpoints is provided below:

Method Path Description
POST /db/_index Create a new index
GET /db/_index List all indexes
DELETE /db/_index Delete an index
POST /db/_find Find documents using an index

List all indexes

When you make a GET request to /db/_index, you get a list of all indexes in the database. In addition to the information available through this API, indexes are also stored in design documents <index-functions>. Design documents are regular documents that have an ID starting with _design/. Design documents can be retrieved and modified in the same way as any other document, although this is not necessary when using Cloudant Query.

Response body

An example of a response body with two indexes

{
    "indexes": [
        {
            "ddoc": "_design/2ec1805041b2c3dcdef1d07a8ea1dc51ba3decfa",
            "name": "foo-bar-index",
            "type": "json",
            "def": {
                "fields": [
                    {"foo":"asc"},
                    {"bar":"asc"}
                ]
            }
        },
        {
            "ddoc": "_design/1f003ce73056238720c2e8f7da545390a8ea1dc5",
            "name": "baz-index",
            "type": "json",
            "def": {
                "fields": [
                    {"baz":"desc"}
                 ]
             }
         }
    ]
}

Deleting an index

Finding documents using an index

Request body

Example request body for finding documents using an index:

{
    "selector": {
        "bar": {"$gt": 1000000}
    },
    "fields": ["_id", "_rev", "foo", "bar"],
    "sort": [{"bar": "asc"}],
    "limit": 10,
    "skip": 0
}

The bookmark field is used for paging through result sets. Every query returns an opaque string under the bookmark key that can then be passed back in a query to get the next page of results. If any part of the query other than bookmark changes between requests, the results are undefined.

The limit and skip values are exactly as you would expect. While skip exists, it is not intended to be used for paging. The reason is that the bookmark feature is more efficient.

Response body

Example response when finding documents using an index:

{
    "docs":[
        {
            "_id": "2",
            "_rev": "1-9f0e70c7592b2e88c055c51afc2ec6fd",
            "foo": "test",
            "bar": 2600000
        },
        {
            "_id": "1",
            "_rev": "1-026418c17a353a9b73a6ccac19c142a4",
            "foo":"another test",
            "bar":9800000
        }
    ]
}

Selector Syntax

The Cloudant Query language is expressed as a JSON object describing documents of interest. Within this structure, you can apply conditional logic using specially named fields.

Selector basics

A simple selector

"selector": {
  "name": "Paul"
}

Elementary selector syntax requires you to specify one or more fields, and the corresponding values required for those fields. This selector matches all documents whose "name" field has the value "Paul".

A simple selector for a full text index

"selector": {
  "$text": "Bond"
}

If you created a full text index by specifying "type":"text" when the index was created, you can use the $text operator to select matching documents. In this example, the full text index is inspected to find any document that includes the word “Bond”.

A simple selector, inspecting specific fields

"selector": {
  "$text": "Bond"
},
"fields": [
  "title",
  "character"
]

In this example, the full text index is inspected to find any document that includes the word “Bond” in the fields title or character.

You can create more complex selector expressions by combining operators. However, for Cloudant Query indexes of type json, you cannot use ‘combination’ or ‘array logical’ operators such as $regex as the basis of a query. Only the equality operators such as $eq, $gt, $gte, $lt, and $lte (but not $ne) can be used as the basis of a more complex query. For more information about creating complex selector expressions, see Creating selector expressions.

Selector with two fields

A more complex selector

"selector": {
  "name": "Paul",
  "location": "Boston"
}

This selector matches any document with a name field containing “Paul”, and that also has a location field with the value “Boston”.

Subfields

Example of a field and subfield selector, using a standard JSON structure:

"selector": {
  "location": {
    "city": "Omaha"
  }
}

A more complex selector enables you to specify the values for field of nested objects, or subfields. For example, you might use a standard JSON structure for specifying a field and subfield.

Example of an equivalent dot-notation field and subfield selector:

"selector": {
  "location.city": "Omaha"
}

An abbreviated equivalent uses a dot notation to combine the field and subfield names into a single name.

Operators

Example selector using an operator to match any document, where the age field has a value greater than 20:

{
  "age": {
    "$gt": 20
  }
}

Operators are identified by the use of a dollar sign ($) prefix in the name field.

There are two core types of operators in the selector syntax:

In general, combination operators are applied at the top level of selection. They are used to combine conditions, or to create combinations of conditions, into one selector.

Every explicit operator has the form:

{"$operator": argument}

A selector without an explicit operator is considered to have an implicit operator. The exact implicit operator is determined by the structure of the selector expression.

Implicit Operators

There are two implicit operators:

In a selector, any field containing a JSON value, but that has no operators in it, is considered to be an equality condition. The implicit equality test applies also for fields and subfields.

Any JSON object that is not the argument to a condition operator is an implicit $and operator on each field.

Example of the implicit equality operator

{
  "foo": "bar"
}

In this example, there must be a field foo in a matching document, and the field must have a value exactly equal to “bar”.

Example of an explicit equality operator

{
  "foo": {
    "$eq": "bar"
  }
}

You can also make the equality operator explicit.

Example of implicit operator applied to a subfield test

{
  "foo": {
    "bar": "baz"
  }
}

In the example using subfields, the required field foo in a matching document must also have a subfield bar and the subfield must have a value exactly equal to “baz”.

Example of an explicit equality operator

{
  "foo": {
    "$eq": {
      "bar": "baz"
    }
  }
}

$eq operator used with full text indexing

{
  "selector": {
    "year": {
      "$eq": 2001
    }
  },
  "sort": [
    "title:string"
  ],
  "fields": [
    "title"
  ]
}

$eq operator used with database indexed on the field "year"

{
  "selector": {
    "year": {
      "$eq": 2001
    }
  },
  "sort": [
    "year"
  ],
  "fields": [
    "year"
  ]
}

Again, you can make the equality operator explicit.

Example of an implicit $and operator

{
  "foo": "bar",
  "baz": true
}

In this example, the field foo must be present and contain the value bar and the field baz must exist and have the value true.

Example of using explicit $and and $eq operators

{
  "$and": [
    {
      "foo": {
        "$eq": "bar"
      }
    },
    {
      "baz": {
        "$eq": true
      }
    }
  ]
}

You can make both the $and operator and the equality operator explicit.

Explicit operators

All operators, apart from ‘Equality’ and ‘And’, must be stated explicitly.

Combination Operators

Combination operators are used to combine selectors. In addition to the common boolean operators found in most programming languages, there are two combination operators ($all and $elemMatch) that help you work with JSON arrays.

A combination operator takes a single argument. The argument is either another selector, or an array of selectors.

The list of combination operators:

Operator Argument Purpose
$and Array Matches if all the selectors in the array match.
$or Array Matches if any of the selectors in the array match. All selectors must use the same index.
$not Selector Matches if the given selector does not match.
$nor Array Matches if none of the selectors in the array match.
$all Array Matches an array value if it contains all the elements of the argument array.
$elemMatch Selector Matches an array value if any of the elements in the array are matched by the argument to $elemMatch, then returns only the first match.

Examples of combination operators

The $and operator

$and operator used with full text indexing

{
  "selector": {
    "$and": [
      {
        "$text": "schwarzenegger"
      },
      {
        "year": {
          "$in": [2005, 2010, 2015]
        }
      }
    ]
  },
  "fields": [
    "year",
    "title",
    "cast"
  ]
}

$and operator used with primary index

{
  "selector": {
    "$and": [
      {
        "_id": { "$gt": null }
      },
      {
        "year": {
          "$in": [2014, 2015]
        }
      }
    ]
  },
  "fields": [
    "year",
    "_id",
    "title"
  ],
  "limit": 10
}

The $and operator matches if all the selectors in the array match.

The $or operator

$or operator used with full text indexing

{
  "selector": {
    "$or": [
      { "director": "George Lucas" },
      { "director": "Steven Spielberg" }
    ]
  },
  "fields": [
    "title",
    "director",
    "year"
  ]
}

$or operator used with database indexed on the field "year"

{
  "selector": {
    "year": 1977,
    "$or": [
      { "director": "George Lucas" },
      { "director": "Steven Spielberg" }
    ]
  },
  "fields": [
    "title",
    "director",
    "year"
  ]
}

The $or operator matches if any of the selectors in the array match.

The $not operator

$not operator used with full text indexing

{
  "selector": {
    "year": {
      "$gte": 1900
    },
    "year": {
      "$lte": 1903
    },
    "$not": {
      "year": 1901
    }
  },
  "fields": [
    "title",
    "year"
  ]
}

$not operator used with database indexed on the field "year"

{
  "selector": {
    "year": {
      "$gte": 1900
    },
    "year": {
      "$lte": 1903
    },
    "$not": {
      "year": 1901
    }
  },
  "fields": [
    "title",
    "year"
  ]
}

The $not operator matches if the given selector does not match.

The $nor operator

$nor operator used with full text indexing

{
  "selector": {
    "year": {
      "$gte": 1900
    },
    "year": {
      "$lte": 1910
    },
    "$nor": [
      { "year": 1901 },
      { "year": 1905 },
      { "year": 1907 }
    ]
  },
  "fields": [
    "title",
    "year"
  ]
}

$nor operator used with database indexed on the field "year"

{
  "selector": {
    "year": {
      "$gte": 1900
    },
    "year": {
      "$lte": 1910
    },
    "$nor": [
      { "year": 1901 },
      { "year": 1905 },
      { "year": 1907 }
    ]
  },
  "fields": [
    "title",
    "year"
  ]
}

The $nor operator matches if the given selector does not match.

The $all operator

$all operator used with full text indexing

{
  "selector": {
    "genre": {
      "$all": ["Comedy","Short"]
      }
  },
  "fields": [
    "title",
    "genre"
  ],
  "sort": [
    "title:string"
  ]
}

$all operator used with primary database index

{
  "selector": {
    "_id": {
      "$gt": null
    },
    "genre": {
      "$all": ["Comedy","Short"]
      }
  },
  "fields": [
    "title",
    "genre"
  ],
  "limit": 10
}

The $all operator matches an array value if it contains all the elements of the argument array.

The $elemMatch operator

$elemMatch operator used with full text indexing

{
  "selector": {
    "genre": {
      "$elemMatch": {
        "$eq": "Horror"
      }
    }
  },
  "fields": [
    "title",
    "genre"
  ]
}

$elemMatch operator used with primary database index

{
  "selector": {
    "_id": { "$gt": null },
    "genre": {
      "$elemMatch": {
        "$eq": "Horror"
      }
    }
  },
  "fields": [
    "title",
    "genre"
  ],
  "limit": 10
}

The $elemMatch operator matches an array value if any of the elements in the array are matched by the argument to $elemMatch, then returns only the first match.

Condition Operators

Condition operators are specific to a field, and are used to evaluate the value stored in that field. For instance, the basic $eq operator matches when the specified field contains a value that is equal to the supplied argument.

The basic equality and inequality operators common to most programming languages are supported. In addition, some ‘meta’ condition operators are available. Some condition operators accept any valid JSON content as the argument. Other condition operators require the argument to be in a specific JSON format.

Operator type Operator Argument Purpose
(In)equality $lt Any JSON The field is less than the argument.
$lte Any JSON The field is less than or equal to the argument.
$eq Any JSON The field is equal to the argument.
$ne Any JSON The field is not equal to the argument.
$gte Any JSON The field is greater than or equal to the argument.
$gt Any JSON The field is greater than the argument.
Object $exists Boolean Check whether the field exists or not, regardless of its value.
$type String Check the document field’s type. Valid values are “null”, “boolean”, “number”, “string”, “array”, and “object”.
Array $in Array of JSON values The document field must exist in the list provided.
$nin Array of JSON values The document field must not exist in the list provided.
$size Integer Special condition to match the length of an array field in a document. Non-array fields cannot match this condition.
Miscellaneous $mod [Divisor, Remainder] Divisor and Remainder are both positive integers greater than 0. Matches documents where (field % Divisor == Remainder) is true. This is false for any non-integer field.
$regex String A regular expression pattern to match against the document field. Only matches when the field is a string value and matches the supplied regular expression.

Examples of condition operators

The $lt operator

$lt operator used with full text indexing

{
  "selector": {
    "year": {
      "$lt": 1900
    }
  },
  "sort": [
    "year:number",
    "title:string"
  ],
  "fields": [
    "year",
    "title"
  ]
}

$lt operator used with database indexed on the field "year"

{
  "selector": {
    "year": {
      "$lt": 1900
    }
  },
  "sort": [
    "year"
  ],
  "fields": [
    "year"
  ]
}

The $lt operator matches if the specified field content is less than the argument.

The $lte operator

$lte operator used with full text indexing

{
  "selector": {
    "year": {
      "$lte": 1900
    }
  },
  "sort": [
    "year:number",
    "title:string"
  ],
  "fields": [
    "year",
    "title"
  ]
}

$lte operator used with database indexed on the field "year"

{
  "selector": {
    "year": {
      "$lte": 1900
    }
  },
  "sort": [
    "year"
  ],
  "fields": [
    "year"
  ]
}

The $lte operator matches if the specified field content is less than or equal to the argument.

The $eq operator

$eq operator used with full text indexing

{
  "selector": {
    "year": {
      "$eq": 2001
    }
  },
  "sort": [
    "title:string"
  ],
  "fields": [
    "title"
  ]
}

$eq operator used with database indexed on the field "year"

{
  "selector": {
    "year": {
      "$eq": 2001
    }
  },
  "sort": [
    "year"
  ],
  "fields": [
    "year"
  ]
}

The $eq operator matches if the specified field content is equal to the supplied argument.

The $ne operator

$ne operator used with full text indexing

{
  "selector": {
    "year": {
      "$ne": 1892
    }
  },
  "fields": [
    "year"
  ],
  "sort": [
    "year:number"
  ]
}

$ne operator used with primary index

{
  "selector": {
    "_id": {
      "$gt": null
    },
    "year": {
      "$ne": 1892
    }
  },
  "fields": [
    "year"
  ],
  "limit": 10
}

The $ne operator matches if the specified field content is not equal to the supplied argument.

The $gte operator

$gte operator used with full text indexing

{
  "selector": {
    "year": {
      "$gte": 2001
    }
  },
  "sort": [
    "year:number",
    "title:string"
  ],
  "fields": [
    "year",
    "title"
  ]
}

$gte operator used with database indexed on the field "year"

{
  "selector": {
    "year": {
      "$gte": 2001
    }
  },
  "sort": [
    "year"
  ],
  "fields": [
    "year"
  ]
}

The $gte operator matches if the specified field content is greater than or equal to the argument.

The $gt operator

$gte operator used with full text indexing

{
  "selector": {
    "year": {
      "$gt": 2001
    }
  },
  "sort": [
    "year:number",
    "title:string"
  ],
  "fields": [
    "year",
    "title"
  ]
}

$gt operator used with database indexed on the field "year"

{
  "selector": {
    "year": {
      "$gt": 2001
    }
  },
  "sort": [
    "year"
  ],
  "fields": [
    "year"
  ]
}

The $gt operator matches if the specified field content is greater than the argument.

The $exists operator

$exists operator used with full text indexing

{
  "selector": {
    "year": 2015,
    "title": {
      "$exists": true
    }
  },
  "fields": [
    "year",
    "_id",
    "title"
  ]
}

$exists operator used with database indexed on the field "year"

{
  "selector": {
    "year": 2015,
    "title": {
      "$exists": true
    }
  },
  "fields": [
    "year",
    "_id",
    "title"
  ]
}

The $exists operator matches if the field exists, regardless of its value.

The $type operator

$type operator used with full text indexing

{
  "selector": {
    "year": {
      "$type": "number"
    }
  },
  "fields": [
    "year",
    "_id",
    "title"
  ]
}

$type operator used with primary index

{
  "selector": {
    "_id": { "$gt": null },
    "year": {
      "$type": "number"
    }
  },
  "fields": [
    "year",
    "_id",
    "title"
  ]
}

The $type operator requires that the specified document field is of the correct type.

The $in operator

$in operator used with full text indexing

{
  "selector": {
    "year": {
      "$in": [2010,2015]
    }
  },
  "fields": [
    "year",
    "_id",
    "title"
  ],
  "sort": [
    "year:number"
  ]
}

$in operator used with primary index

{
  "selector": {
    "_id": { "$gt": null },
    "year": {
      "$in": [2010, 2015]
    }
  },
  "fields": [
    "year",
    "_id",
    "title"
  ],
  "limit": 10
}

The $in operator requires that the document field must exist in the list provided.

The $nin operator

$nin operator used with full text indexing

{
  "selector": {
    "year": {
      "$gt": 2009,
      "$nin": [2010, 2015]
    }
  },
  "fields": [
    "year",
    "_id",
    "title"
  ],
  "sort": [
    "year:number"
  ]
}

$nin operator used with primary index

{
  "selector": {
    "_id": { "$gt": null },
    "year": {
      "$nin": [2010, 2015]
    }
  },
  "fields": [
    "year",
    "_id",
    "title"
  ],
  "limit": 10
}

The $nin operator requires that the document field must not exist in the list provided.

The $size operator

$size operator used with full text indexing

{
  "selector": {
    "genre": {
      "$size": 4
    }
  },
  "fields": [
    "title",
    "genre"
  ],
  "limit": 1000
}

$size operator used with primary index

{
  "selector": {
    "_id": {
      "$gt": null
    },
    "genre": {
      "$size": 4
    }
  },
  "fields": [
    "title",
    "genre"
  ],
  "limit": 25
}

The $size operator matches the length of an array field in a document.

The $mod operator

$mod operator used with full text indexing

{
  "selector": {
    "year": {
      "$mod": [100,0]
    }
  },
  "fields": [
    "title",
    "year"
  ],
  "limit": 50
}

$mod operator used with primary index

{
  "selector": {
    "_id": {
      "$gt": null
    },
    "year": {
      "$mod": [100,0]
    }
  },
  "fields": [
    "title",
    "year"
  ],
  "limit": 50
}

The $mod operator matches documents where (field % Divisor == Remainder) is true. Always evaluates to false for any non-integer field.

The $regex operator

$regex operator used with full text indexing

{
  "selector": {
    "cast": {
      "$elemMatch": {
        "$regex": "^Robert"
      }
    }
  },
  "fields": [
    "title",
    "cast"
  ],
  "limit": 10
}

$regex operator used with primary index

{
  "selector": {
    "_id": {
      "$gt": null
    },
    "cast": {
      "$elemMatch": {
        "$regex": "^Robert"
      }
    }
  },
  "fields": [
    "title",
    "cast"
  ],
  "limit": 10
}

The $regex operator matches when the field is a string value and matches the supplied regular expression.

Creating selector expressions

We have seen examples of combining selector expressions, such as using explicit $and and $eq operators. In general, whenever you have an operator that takes an argument, that argument can itself be another operator with arguments of its own. This enables us to build up more complex selector expressions.

However, not all operators can be used as the base or starting point of the selector expression when using indexes of type json.

Example of an invalid selector expression:

{
  "selector": {
    "afieldname": {
      "$regex": "^A"
    }
  }
}

Example response to an invalid selector expression:

{
  error: "no_usable_index"
  reason: "There is no operator in this selector can used with an index."
}

For example, if you try to perform a query that attempts to match all documents that have a field called afieldname containing a value that begins with the letter A, you get an error: "no_usable_index" error message.

Example use of an equality operator to enable a selector expression:

{
  "selector": {
    "_id": {
      "$gt": null
    },
    "afieldname": {
      "$regex": "^A"
    }
  }
}

A solution is to use an equality operator as the basis of the query. You can add a ‘null’ or always true expression as the basis of the query. For example, you could first test that the document has an _id value:

"_id": { "$gt": null }

This expression is always true, enabling the remainder of the selector expression to be applied.

Most selector expressions work exactly as you would expect for the given operator. The matching algorithms used by the $regex operator are currently based on the Perl Compatible Regular Expression (PCRE) library. However, not all of the PCRE library is implemented, and some parts of the $regex operator go beyond what PCRE offers. For more information about what is implemented, see the Erlang Regular Expression information.

Sort Syntax

Example of simple sort syntax:

[{"fieldName1": "desc"}, {"fieldName2": "desc" }]

The sort field contains a list of field name and direction pairs, expressed as a basic array. The first field name and direction pair is the topmost level of sort. The second pair, if provided, is the next level of sort.

The field can be any field, using dotted notation if desired for sub-document fields.

The direction value is "asc" for ascending, and "desc" for descending.

A simple query, using sorting:

{
    "selector": {"Actor_name": "Robert De Niro"},
    "sort": [{"Actor_name": "asc"}, {"Movie_runtime": "asc"}]
}

A typical requirement is to search for some content using a selector, then to sort the results according to the specified field, in the required direction.

To use sorting, ensure that:

If the direction is ascending, you can use a string instead of an object to specify the sort fields.

For field names in text search sorts, it is sometimes necessary for a field type to be specified, for example:

{ "<fieldname>:string": "asc"}

If possible, an attempt is made to discover the field type based on the selector. In ambiguous cases the field type must be provided explicitly.

Filtering fields

Example of selective retrieval of fields from matching documents:

{
    "selector": { "Actor_name": "Robert De Niro" },
    "fields": ["Actor_name", "Movie_year", "_id", "_rev"]
}

It is possible to specify exactly which fields are returned for a document when selecting from a database. The two advantages are:

The fields returned are specified as an array.

Note about text indexes

The basic premise for full text indexes is that a document is “expanded” into a list of key/value pairs that are indexed by Lucene. This allows us to make use of Lucene’s search syntax as a basis for the query capability.

While supporting enhanced searches, this technique does have certain limitations. For example, it might not always be clear whether content for an expanded document came from individual elements or an array.

The query mechanism resolves this by preferring to return ‘false positive’ results. In other words, if a match would have be found as a result of searching for either an individual element, or an element from an array, then the match is considered to have succeeded.

Selector Translation

Example query to be translated

{"age": {"$gt": 5}}

Corresponding Lucene query

(age_3anumber:{5 TO Infinity])

A standard Lucene search expression would not necessarily fully ‘understand’ Cloudant’s JSON based query syntax. Therefore, a translation between the two formats takes place.

In the example given, the JSON query approximates to the English phrase: “match if the age expressed as a number is greater than five and less than or equal to infinity”. The Lucene query corresponds to that phrase, where the text _3a within the fieldname corresponds to the age:number field, and is an example of the document content expansion mentioned earlier.

A more complex example

JSON query to be translated

{
  "$or": [
  {"age": {"$gt": 5}},
  {"twitter":{"$exists":true}},
  {"type": {"$in": [
    "starch",
    "protein"
  ]}}
  ]
}

Corresponding Lucene query
(the ‘#’ comment is not valid Lucene syntax, but helps explain the query construction):

(
# Search for age > 5
(age_3anumber:{5 TO Infinity])
# Search for documents containing the twitter field
(($fieldnames:twitter_3a*) OR ($fieldnames:twitter_2e*))
# Search for type = starch
(
((type_3astring:starch) OR (type_2e_5b_5d_3astring:starch))
# Search for type = protein
((type_3astring:protein) OR (type_2e_5b_5d_3astring:protein))
)
)

This example illustrates some important points.

In the {"$exists":true} JSON query, we use a two clause OR query for the twitter field, ending in _3a* and _2e*. This clause searches the $fieldnames field for entries that contain either twitter.* or twitter:*. The reason is to match when the value is an array or an object. Implementing this as two phrases instead of a single twitter* query prevents an accidental match with a field name such as twitter_handle or similar.

The last of the three main clauses, where we search for starch or protein, is more complicated. The $in operator has some special semantics for array values that are inherited from MongoDB’s documented behavior. In particular, the $in operator applies to the value OR any of the values contained in an array named by the given field. In our example, this means that both "type":"starch" AND "type":["protein"] would match the example argument to $in. We saw earlier that type_3astring translates to type:string. The second type_2e_5b_5d_3astring phrase translates to type.[]:string, which is an example of the expanded array indexing.

Example: Movies Demo Database

Obtaining a copy of the Cloudant Query movie database:

POST /_replicator HTTP/1.1
Host: user.cloudant.com
Content-Type: application/json

{
  "source": "https://examples.cloudant.com/query-movies",
  "target": "https://<user:password>@<user>.cloudant.com/my-movies",
  "create_target": true,
  "use_checkpoints": false
}
curl 'https://<user:password>@<user>.cloudant.com/_replicator' \
  -X POST \
  -H 'Content-Type: application/json' \
  -d '{
    "source": "https://examples.cloudant.com/query-movies",
    "target": "https://<user:password>@<user>.cloudant.com/my-movies",
    "create_target": true,
    "use_checkpoints": false
}'

Results after successful replication of the Cloudant Query movie database:

{
  "ok": true,
  "use_checkpoints": false
}

To describe full text indexes, it is helpful to have a large collection of data to work with. A suitable collection is available in the example Cloudant Query movie database: query-movies. You can obtain a copy of this database in your database, with the name my-movies, by running the command shown.

The sample database contains approximately 3,000 documents, and is just under 1 MB in size.

Creating a text index for your sample database:

POST /my-movies/_index HTTP/1.1
Host: user.cloudant.com
Content-Type: application/json

{
  "index": {},
  "type": "text"
}
curl 'https://<user:password>@<user>.cloudant.com/my-movies/_index' \
  -X POST \
  -H 'Content-Type: application/json' \
  -d '{"index": {}, "type": "text"}'

Response after creating a text index:

{
  "result": "created"
}

Before we can search the content, we must index it. We do this by creating a text index for the documents.

Searching for a specific document within the database:

POST /my-movies/_find HTTP/1.1
Host: user.cloudant.com
Content-Type: application/json

{
  "selector": {
    "Person_name":"Zoe Saldana"
  }
}
curl -X POST -H "Content-Type: application/json" \
        https://<user:password>@<user>.cloudant.com/my-movies/_find \
        -d '{"selector": {"Person_name":"Zoe Saldana"}}'

Example result from the search:

{
  "docs": [
    {
      "_id": "d9e6a7ae2363d6cfe81af75a3941110b",
      "_rev": "1-556aec0e89fa13769fbf59d651411528",
      "Movie_runtime": 162,
      "Movie_rating": "PG-13",
      "Person_name": "Zoe Saldana",
      "Movie_genre": "AVYS",
      "Movie_name": "Avatar",
      "Movie_earnings_rank": "1",
      "Person_pob": "New Jersey, USA",
      "Movie_year": 2009,
      "Person_dob": "1978-06-19"
    }
  ],
  "bookmark": "g2wA ... Omo"
}

The most obvious difference in the results you get when using full text indexes is the inclusion of a large bookmark field. The reason is that text indexes are different to view-based indexes. For more flexibility when working with the results obtained from a full text query, you can supply the bookmark value as part of the request body. Using the bookmark enables you to specify which page of results you require.

Example of a slightly more complex search:

POST /my-movies/_find HTTP/1.1
Host: user.cloudant.com
Content-Type: application/json

{
  "selector": {
    "Person_name":"Robert De Niro",
    "Movie_year": 1978
  }
}
curl -X POST -H "Content-Type: application/json" \
        https://<user:password>@<user>.cloudant.com/my-movies/_find \
        -d '{"selector": {"Person_name":"Robert De Niro", "Movie_year": 1978}}'

Example result from the search:

{
  "docs": [
    {
      "_id": "d9e6a7ae2363d6cfe81af75a392eb9f2",
      "_rev": "1-9faa75d7ea524448b1456a6c69a4391a",
      "Movie_runtime": 183,
      "Movie_rating": "R",
      "Person_name": "Robert De Niro",
      "Movie_genre": "DW",
      "Movie_name": "Deer Hunter, The",
      "Person_pob": "New York, New York, USA",
      "Movie_year": 1978,
      "Person_dob": "1943-08-17"
    }
  ],
  "bookmark": "g2w ... c2o"
}

Example of searching within a range:

POST /my-movies/_find HTTP/1.1
Host: user.cloudant.com
Content-Type: application/json

{
  "selector": {
    "Person_name":"Robert De Niro",
    "Movie_year": {
      "$in": [1974, 2009]
    }
  }
}
curl -X POST -H "Content-Type: application/json" \
        https://<user:password>@<user>.cloudant.com/my-movies/_find \
        -d '{"selector": {"Person_name":"Robert De Niro", "Movie_year": { "$in": [1974, 2009]}}}'

Example result from the search:

{
  "docs": [
    {
      "_id": "d9e6a7ae2363d6cfe81af75a392eb9f2",
      "_rev": "1-9faa75d7ea524448b1456a6c69a4391a",
      "Movie_runtime": 183,
      "Movie_rating": "R",
      "Person_name": "Robert De Niro",
      "Movie_genre": "DW",
      "Movie_name": "Deer Hunter, The",
      "Person_pob": "New York, New York, USA",
      "Movie_year": 1978,
      "Person_dob": "1943-08-17"
    }
  ],
  "bookmark": "g2w ... c2o"
}

Design Documents

Instead of storing data in a document, you might also have special documents that store other content, such as functions. The special documents are called “design documents”.

Design documents are documents that have an _id beginning with _design/. They can be read and updated in the same way as any other document in the database. Cloudant reads specific fields and values of design documents as functions. Design documents are used to build indexes, validate updates, and format query results.

Creating or updating a design document

To create a design document, upload it to the specified database.

In these examples, $VARIABLES might refer to standard and design documents. To distinguish between them, standard documents have an _id indicated by $DOCUMENT_ID, while design documents have an _id indicated by $DESIGN_ID.

The structure of design document is as follows:

Copying a Design Document

You can copy the latest version of a design document to a new document by specifying the base document and target document. The copy is requested using the COPY HTTP request.

Example command to copy a design document:

COPY /recipes/_design/recipes HTTP/1.1
Content-Type: application/json
Destination: /recipes/_design/recipelist

Example response to copy command:

{
  "id" : "recipes/_design/recipelist"
  "rev" : "1-9c65296036141e575d32ba9c034dd3ee",
}

An example request to copy the design document recipes to the new design document recipelist produces a response containing the ID and revision of the new document.

The structure of the copy command

The source design document is specified on the request line, with the Destination HTTP Header of the request specifying the target document.

Copying from a specific revision

Example command to copy a specific revision of the design document:

COPY /recipes/_design/recipes?rev=1-e23b9e942c19e9fb10ff1fde2e50e0f5 HTTP/1.1
Content-Type: application/json
Destination: recipes/_design/recipelist

To copy from a specific version, add the rev argument to the query string.

The new design document is created using the specified revision of the source document.

Copying to an existing design document

Example command to overwrite an existing copy of the design document:

COPY /recipes/_design/recipes
Content-Type: application/json
Destination: recipes/_design/recipelist?rev=1-9c65296036141e575d32ba9c034dd3ee

Example response to overwriting successfully an existing design document:

{
    "id" : "recipes/_design/recipes"
    "rev" : "2-55b6a1b251902a2c249b667dab1c6692",
}

To copy to an existing document, specify the current revision string for the target document, using the rev parameter to the Destination HTTP Header string.

The return value is the new revision of the copied document.

Deleting a design document

Example command to delete a design document:

DELETE /recipes/_design/recipes?rev=2-ac58d589b37d01c00f45a4418c5a15a8 HTTP/1.1
Content-Type: application/json

Example response, containing the delete document ID and revision:

{
  "id" : "recipe/_design/recipes"
  "ok" : true,
  "rev" : "3-7a05370bff53186cb5d403f861aca154",
}

You can delete an existing design document. Deleting a design document also deletes all of the associated view indexes, and recovers the corresponding space on disk for the indexes in question.

To delete successfully, you must specify the current revision of the design document using the rev query argument.

The structure of the delete command

Views

An important use of design documents is for creating views. These are discussed in more detail here.

Rewrite rules

Example rewrite rules:

"rewrites": [
  {
    "from": "/",
    "to": "index.html",
    "method": "GET",
    "query": {}
  },
  {
    "from": "/foo/:var",
    "to": "/foo",
    "method": "GET",
    "query": {"v": "var"}
  }
]

A design document can contain rules for URL rewriting, by using an array in the rewrites field. Requests that match the rewrite rules must have a URL path that starts with /$DATABASE/_design/doc/_rewrite.

Each rule is a JSON object with 4 fields:

Field Description
from A path relative to /$DATABASE/_design/doc/_rewrite, used to match URLs to rewrite rules. Path elements that start with a : are treated as variables and match any string that does not contain a /. A * can only appear at the end of the string, and matches any string - including slashes.
to The path (relative to /$DATABASE/_design/doc/ and not including the query part of the URL) that is the result of the rewriting step. Variables captured in from can be used in to. * can also be used and contains everything captured by the pattern in from.
method The HTTP method that should be matched on.
query The query part of the resulting URL. This is a JSON object containing the key/value pairs of the query.

Example rewrite rules

Rule URL Rewrite to Tokens
{"from": "/a/b", "to": "/some/"} /$DATABASE/_design/doc/_rewrite/a/b?k=v /$DATABASE/_design/doc/some/k=v k = v
{"from": "/a/b", "to": "/some/:var"} /$DATABASE/_design/doc/_rewrite/a/b /$DATABASE/_design/doc/some/b?var=b var = b
{"from": "/a", "to": "/some/*"} /$DATABASE/_design/doc/_rewrite/a /$DATABASE/_design/doc/some  
{"from": "/a/*", "to": "/some/*} /$DATABASE/_design/doc/_rewrite/a/b/c /$DATABASE/_design/doc/some/b/c  
{"from": "/a", "to": "/some/*"} /$DATABASE/_design/doc/_rewrite/a /$DATABASE/_design/doc/some  
{"from": "/a/:foo/*","to": "/some/:foo/*"} /$DATABASE/_design/doc/_rewrite/a/b/c /$DATABASE/_design/doc/some/b/c?foo=b foo = b
{"from": "/a/:foo", "to": "/some", "query": { "k": ":foo" }} /$DATABASE/_design/doc/_rewrite/a/b /$DATABASE/_design/doc/some/?k=b&foo=b foo =:= b
{"from": "/a", "to": "/some/:foo" } /$DATABASE/_design/doc/_rewrite/a?foo=b /$DATABASE/_design/doc/some/b&foo=b foo = b

Indexes

All queries operate on pre-defined indexes defined in design documents. These indexes are:

For example, to create a design document used for searching, you must ensure that two conditions are true:

  1. You have identified the document as a design document by having an _id starting with _design/.
  2. A search index has been created within the document by updating the document with the appropriate field or by creating a new document containing the search index.

As soon as the search index design document exists and the index has been built, you can make queries using it.

For more information about search indexing, refer to the search section of this documentation.

General notes on functions in design documents

Functions in design documents are run on multiple nodes for each document and might be run several times. To avoid inconsistencies, they need to be idempotent, meaning they need to behave identically when run multiple times and/or on different nodes. In particular, you should avoid using functions that generate random numbers or return the current time.

List Functions

Example design document referencing a list function:

{
  "_id": "_design/list_example",
  "lists": {
    "FUNCTION_NAME": "function (head, req) { ... }"
  }
}

Example list function:

function (head, req) {
  // specify our headers
  start({
    headers: {
      "Content-Type": 'text/html'
    }
  });
  // send the respond, line by line
  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>');
}

Example query:

GET /$DATABASE/$DESIGN_ID/_list/$LIST_FUNCTION/$MAPREDUCE_INDEX HTTP/1.1
Host: $USERNAME.cloudant.com
curl https://$USERNAME.cloudant.com/$DATABASE/$DESIGN_ID/_list/$LIST_FUNCTION/$MAPREDUCE_INDEX \
     -u $USERNAME
var nano = require('nano');
var account = nano("https://"+$USERNAME+":"+$PASSWORD+"@"+$USERNAME+".cloudant.com");
var db = account.use($DATABASE);

db.view_with_list($DESIGN_ID, $MAPREDUCE_INDEX, $LIST_FUNCTION, function (err, body, headers) {
  if (!err) {
    console.log(body);
  }
});

Use list functions to customize the format of MapReduce query results. They are used when you want to access Cloudant directly from a browser, and need data to be returned in a different format, such as HTML.

List functions require two arguments: head and req.

When you define a list function, you use it by making a GET request to https://$USERNAME.cloudant.com/$DATABASE/$DESIGN_ID/_list/$LIST_FUNCTION/$MAPREDUCE_INDEX. In this request:

The other parameters are the same query parameters used in a MapReduce query.

Field Description
total_rows Number of documents in the view
offset Offset where the document list started

req

Field Description
body Request body data as string. If the request method is GET this field contains the value “undefined”. If the method is DELETE or HEAD the value is “” (empty string).
cookie Cookies object.
form Form data object. Contains the decoded body as key-value pairs if the Content-Type header was application/x-www-form-urlencoded.
headers Request headers object.
id Requested document id string if it was specified or null otherwise.
info Database information
method Request method as string or array. String value is a method as one of: HEAD, GET, POST, PUT, DELETE, OPTIONS, and TRACE. Otherwise it will be represented as an array of char codes.
path List of requested path sections.
peer Request source IP address.
query URL query parameters object. Note that multiple keys are not supported and the last key value suppresses others.
requested_path List of actual requested path section.
raw_path Raw requested path string.
secObj The database’s security object
userCtx Context about the currently authenticated user, specifically their name and roles within the current database.
uuid A generated UUID

Show Functions

Design doc with a show function:

{
  "_id": "_design/show_example",
  "shows": {
    "FUNCTION_NAME": "function (doc, req) { ... }"
  }
}

Example show function:

function (doc, req) {
  if (doc) {
    return "Hello from " + doc._id + "!";
  } else {
    return "Hello, world!";
  }
}

Example query:

GET /$DATABASE/$DESIGN_ID/_show/$SHOW_FUNCTION/$DOCUMENT_ID HTTP/1.1
Host: $USERNAME.cloudant.com
curl https://$USERNAME.cloudant.com/$DATABASE/$DESIGN_ID/_show/$SHOW_FUNCTION/$DOCUMENT_ID \
     -u $USERNAME
var nano = require('nano');
var account = nano("https://"+$USERNAME+":"+$PASSWORD+"@"+$USERNAME+".cloudant.com");
var db = account.use($DATABASE);

db.show($DESIGN_ID, $SHOW_FUNCTION, $DOCUMENT_ID, function (err, body) {
  if (!err) {
    console.log(body);
  }
});

Show functions are similar to list functions but are used to format individual documents. They are used when you want to access Cloudant directly from a browser, and need data to be returned in a different format, such as HTML.

Show functions receive two arguments: doc, and req. doc is the document requested by the show function.

When you have defined a show function, you query it with a GET request to https://$USERNAME.cloudant.com/$DATABASE/$DOCUMENT_ID/_show/$SHOW_FUNCTION/$DESIGN_ID, where $SHOW_FUNCTION is the name of the function that is applied to the document that has $DESIGN_ID as its _id.

Update Handlers

Example design doc:

{
  "_id": "_design/update_example",
  "updates": {
    "UPDATE_HANDLER_NAME": "function (doc, req) { ... }"
  }
}

Example update handler:

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!']
}

Example query:

POST /$DATABASE/$DESIGN_ID/_update/$UPDATE_HANDLER HTTP/1.1
Host: $USERNAME.cloudant.com
Content-Type: application/json
curl https://$USERNAME.cloudant.com/$DATABASE/$DESIGN_ID/_update/$UPDATE_HANDLER \
     -X POST \
     -H "Content-Type: application/json" \
     -u $USERNAME
     -d "$JSON"
var nano = require('nano');
var account = nano("https://"+$USERNAME+":"+$PASSWORD+"@"+$USERNAME+".cloudant.com");
var db = account.use($DATABASE);

db.atomic($DESIGN_ID, $UPDATE_HANDLER, $DOCUMENT_ID, $JSON, function (err, body) {
  if (!err) {
    console.log(body);
  }
});

Update handlers are custom functions that live on Cloudant’s server that will create or update a document. This can, for example, provide server-side modification timestamps, and document updates to individual fields without the latest revision.

Update handlers receive two arguments: doc and req. If a document ID is provided in the request to the update handler, then doc will be the document corresponding with that ID. If no ID was provided, doc will be null.

Update handler functions must return an array of two elements, the first being the document to save (or null, if you don’t want to save anything), and the second being the response body.

Here’s how to query update handlers:

Method URL
POST https://$USERNAME.cloudant.com/$DATABASE/$DESIGN_ID/_update/$UPDATE_HANDLER
PUT https://$USERNAME.cloudant.com/$DATABASE/$DESIGN_ID/_update/$UPDATE_HANDLER/$DOCUMENT_ID

Where $DESIGN_ID is the _id of the document defining the update handler, $UPDATE_HANDLER is the name of the update handler, and $DOCUMENT_ID is the _id of the document you want the handler to, well, handle.

Filter Functions

Example design document:

{
  "_id":"_design/FILTER_EXAMPLE",
  "filters": {
    "FILTER_EXAMPLE": "function (doc, req) { ... }"
  }
}

Filter functions filter the changes feed, removing changes you don’t want to monitor. The filter function is run over every change in the changes feed, and only those for which the function returns true are returned to the client in the response.

Example filter function:

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 receive two arguments: doc and req. doc represents the document being filtered and req contains information about the http request. In most cases, only the doc parameter will be used.

Example query:

GET /$DATABASE/_changes?filter=$DESIGN_ID%2F$FILTER HTTP/1.1
Host: $USERNAME.cloudant.com
curl https://$USERNAME.cloudant.com/$DATABASE/_changes?filter=$DESIGN_ID%2F$FILTER \
     -u $USERNAME
var nano = require('nano');
var account = nano("https://"+$USERNAME+":"+$PASSWORD+"@"+$USERNAME+".cloudant.com");

account.db.changes($DATABASE, {
  // ex: example/filter
  filter: [$DESIGN_ID, $FILTER_FUNCTION].join('/')
}, function (err, body, headers) {
  if (!err) {
    console.log(body);
  }
});

To use a filter function on the changes feed, specify the filter parameter in the _changes query.

Update Validators

Example design document:

{
  "_id": "_design/validator_example",
  "validate_doc_update": "function(newDoc, oldDoc, userCtx, secObj) { ... }"
}

Example update validator:

function(newDoc, oldDoc, userCtx, secObj) {
  if (newDoc.address === undefined) {
     throw({forbidden: 'Document must have an address.'});
  }
}

Example response:

{
  "error": "forbidden",
  "reason": "Document must have an address."
}

Update validators evaluate whether a document should be written to disk when insertions and updates are attempted. They do not require a query because they implicitly run during this process. If a change is rejected, the update validator responds with a custom error.

Update validators get four arguments:

Retrieving information about a design document

Example to get the information for the recipesdd design document in the recipes database:

GET /recipes/_design/recipesdd/_info HTTP/1.1
Host: $USERNAME.cloudant.com
curl https://$USERNAME.cloudant.com/recipes/_design/recipesdd/_info \
     -u $USERNAME

Example JSON structure response:

{
   "name" : "recipesdd"
   "view_index" : {
      "compact_running" : false,
      "updater_running" : false,
      "language" : "javascript",
      "purge_seq" : 10,
      "waiting_commit" : false,
      "waiting_clients" : 0,
      "signature" : "fc65594ee76087a3b8c726caf5b40687",
      "update_seq" : 375031,
      "disk_size" : 16491
   },
}

Obtains information about a given design document, including the index, index size and current status of the design document and associated index information.

The individual fields in the returned JSON structure are detailed below:

Views (MapReduce)

Views are used to obtain data stored within a database. Views are written using Javascript functions.

View concepts

Views are mechanisms for working with document content in databases. A view can selectively filter documents. It can speed up searching for content. It can be used to ‘pre-process’ the results before they are returned to the client.

Views are simply Javascript functions, defined within the view field of a design document. When you use a view, or more accurately when make a query using your view, the system applies the Javascript function to each and every document in the database. Views can be complex. You might choose to define a collection of Javascript functions to create the overall view required.

A simple view

Example of a simple view, using a map function:

function(employee) {
  if(employee.training) {
    emit(employee.number, employee.training);
  }
}

Simplified example data:

{
  "_id":"23598567",
  "number":"23598567",
  "training":"2014/05/21 10:00:00"
}

{
  "_id":"10278947",
  "number":"10278947"
}

{
  "_id":"23598567",
  "number":"23598567",
  "training":"2014/07/30 12:00:00"
}

Example response from running the view query

{
  "total_rows": 2,
  "offset": 0,
  "rows": [
    {
      "id":"23598567",
      "number":"23598567",
      "training":"2014/05/21 10:00:00"
    },

    {
      "id":"23598567",
      "number":"23598567",
      "training":"2014/07/30 12:00:00"
    }

  ]
}

The simplest form of view is a map function. The map function produces output data that represents an analysis (a mapping) of the documents stored within the database.

For example, you might want to find out which employees have had some safety training, and the date when that training was completed. You could do this by inspecting each document, looking for a field in the document called “training”. If the field is present, the employee completed the training on the date recorded as the value. If the field is not present, the employee has not completed the training.

Using the emit function in the example view function makes it easy to produce a list in response to running a query using the view. The list consists of key and value pairs, where the key helps you identify the specific document and the value provides just the precise detail you want. The list also includes metadata such as the number of key:value pairs returned.

Map function examples

Indexing a field

Example of indexing a field:

function(doc) {
  if (doc.foo) {
    emit(doc._id, doc.foo);
  }
}

This map function checks whether the object has a foo field and emits the value of this field. This allows you to query against the value of the foo field.

An index for a one to many relationship

Example of indexing a one to many relationship:

function(doc) {
  if (doc.friends) {
    for (friend in friends) {
      emit(doc._id, { "_id": friend });
    }
  }
}

If the object passed to emit has an _id field, a view query with include_docs set to true will contain the document with the given ID.

Complex Keys

Keys are not limited to simple values. You can use arbitrary JSON values to influence sorting.

When the key is an array, view results can be grouped by a sub-section of the key. For example, if keys have the form [year, month, day] then results can be reduced to a single value or by year, month, or day. See HttpViewApi for more information.

Reduce functions

Example of a reduce function:

function (key, values, rereduce) {
  return sum(values);
}

If a view has a reduce function, it is used to produce aggregate results for that view. A reduce function is passed a set of intermediate values and combines them to a single value. Reduce functions must accept, as input, results emitted by its corresponding map function “‘as well as results returned by the reduce function itself”’. The latter case is referred to as a “rereduce”.

Reduce functions are passed three arguments in the order “key”, “values”, and “rereduce”.

Reduce functions must handle two cases:

  1. When rereduce is false:

    • key will be an array whose elements are arrays of the form [key,id], where key is a key emitted by the map function and “id” is that of the document from which the key was generated.
    • values will be an array of the values emitted for the respective elements in keys, for example: reduce([ [key1,id1], [key2,id2], [key3,id3] ], [value1,value2,value3], false)
  2. When rereduce is true:

    • key will be null.
    • values will be an array of values returned by previous calls to the reduce function, for example: reduce(null, [intermediate1,intermediate2,intermediate3], true)`

Reduce functions should return a single value, suitable for both the “value” field of the final view and as a member of the “values” array passed to the reduce function.

Often, reduce functions can be written to handle rereduce calls without any extra code, like the summation function described previously. In that case, the rereduce argument can be ignored.

Built-in reduce functions

For performance reasons, a few simple reduce functions are built in. To use one of the built-in functions, put its name into the reduce field of the view object in your design document.

Function Description
_sum Produces the sum of all values for a key, values must be numeric
_count Produces the row count for a given key, values can be any valid json
_stats Produces a json structure containing sum, count, min, max and sum squared, values must be numeric

By feeding the results of reduce functions back into the reduce function, MapReduce is able to split up the analysis of huge datasets into discrete, parallelized tasks, which can be completed much faster.

Dbcopy

If the dbcopy field of a view is set, the view contents will be written to a database of that name. If dbcopy is set, the view must also have a reduce function. For every key/value pair created by a reduce query with group set to true, a document will be created in the dbcopy database. If the database does not exist, it will be created. The documents created have the following fields:

Field Description
key The key of the view result. This can be a string or an array.
value The value calculated by the reduce function.
_id The ID is a hash of the key.
salt This value is an implementation detail used internally.
partials This value is an implementation detail used internally.

Storing the view definition

Example for PUTting a view into a design document (training):

PUT /$DATABASE/_design/training HTTP/1.1
Content-Type: application/json
curl -X PUT https://$USERNAME:$PASSWORD@$USERNAME.cloudant.com/$DATABASE/_design/training --data-binary @view.def
# where the design document is stored in the file `view.def`

Example format for the view:

{
  "views" : {
    "hadtraining" : {
      "map" : "function(employee) { if(employee.training) { emit(employee.number, employee.training); } }"
    }
  }
}

Each view is a Javascript function. Views are stored in design documents. So, to store a view, we simply store the function definition within a design document. A design document can be created or updated just like any other document.

Do this by PUTting the view definition content into a _design document. In this example, the hadtraining view is defined as a map function, and is available within the views field of the design document.

Using Views

Views enable you to search for content within a database, that matches specific criteria. The criteria are specified within the view definition, or supplied as arguments when you use the view.

Executes the specified view-name from the specified design-doc design document.

Query Arguments

Example of retrieving a list of the first five documents from a database, applying the user-created by_title view:

GET /<database>/_design/<design-doc>/_view/by_title?limit=5 HTTP/1.1
Accept: application/json
Content-Type: application/json

Example response:

{
   "offset" : 0,
   "rows" : [
      {
         "id" : "3-tiersalmonspinachandavocadoterrine",
         "key" : "3-tier salmon, spinach and avocado terrine",
         "value" : [
            null,
            "3-tier salmon, spinach and avocado terrine"
         ]
      },
      {
         "id" : "Aberffrawcake",
         "key" : "Aberffraw cake",
         "value" : [
            null,
            "Aberffraw cake"
         ]
      },
      {
         "id" : "Adukiandorangecasserole-microwave",
         "key" : "Aduki and orange casserole - microwave",
         "value" : [
            null,
            "Aduki and orange casserole - microwave"
         ]
      },
      {
         "id" : "Aioli-garlicmayonnaise",
         "key" : "Aioli - garlic mayonnaise",
         "value" : [
            null,
            "Aioli - garlic mayonnaise"
         ]
      },
      {
         "id" : "Alabamapeanutchicken",
         "key" : "Alabama peanut chicken",
         "value" : [
            null,
            "Alabama peanut chicken"
         ]
      }
   ],
   "total_rows" : 2667
}
Argument Description Optional Type Default Supported values
descending Return the documents in ‘descending by key’ order. yes Boolean false
endkey Stop returning records when the specified key is reached. yes String or JSON array
endkey_docid Stop returning records when the specified document ID is reached. yes String
group Using the reduce function, group the results to a group or single row. yes Boolean false
group_level Only applicable if the view uses complex keys: keys that are JSON arrays. Groups reduce results for the specified number of array fields. yes Numeric
include_docs Include the full content of the documents in the response. yes Boolean false
inclusive_end Include rows with the specified endkey. yes Boolean true
key Return only documents that match the specified key. Note: Keys are JSON values, and must be URL encoded. yes JSON strings or arrays
keys Return only documents that match the specified keys. Note: Keys are JSON values and must be URL encoded. yes Array of JSON strings or arrays
limit Limit the number of returned documents to the specified count. yes Numeric
reduce Use the reduce function. yes Boolean true
skip Skip this number of rows from the start. yes Numeric 0
stale Allow the results from a stale view to be used. This makes the request return immediately, even if the view has not been completely built yet. If this parameter is not given, a response is returned only after the view has been built. yes String false ok: Allow stale views.
update_after: Allow stale views, but update them immediately after the request.
startkey Return records starting with the specified key. yes String or JSON array
startkey_docid Return records starting with the specified document ID. yes String

Indexes

When a view is defined in a design document, a corresponding index is also created, based on the information defined within the view. Indexes let you select for documents by criteria other than their _id field, for instance by a field or combination of fields or by a value that is computed based on the contents of the document. The index is populated as soon as the design document is created. On large databases, this process might take a while.

The index content is updated incrementally and automatically when any one of the following three events has occurred:

View indexes are rebuilt entirely when the view definition changes or when another view definition in the same design document changes. This ensures that changes to the view definitions are reflected in the view indexes. To achieve this, a ‘fingerprint’ of the view definition is created whenever the design document is updated. If the fingerprint changes, then the view indexes are completely rebuilt.

If the database has been updated recently, there might be a delay in returning the results when the view is accessed. The delay is affected by the number of changes to the database, and whether the view index is not current because the database content has been modified.

It is not possible to eliminate these delays, in the case of newly created databases you might reduce them by creating the view definition in the design document in your database before inserting or updating documents. This causes incremental updates to the index when the documents or inserted.

If speed of response is more important than having completely up-to-date data, an alternative is to allow users to access an old version of the view index. In effect, the user has an immediate response from ‘stale’ index content, rather than waiting for the index to be updated. Depending on the document contents, using a stale view might not return the latest information. Nevertheless, a stale view returns the results of the view query quickly, by using an existing version of the index.

Accessing a stale view

For example, to access the existing stale view by_recipe in the recipes design document, you would use a request similar to: /recipes/_design/recipes/_view/by_recipe?stale=ok

Making use of a stale view has consequences. In particular, accessing a stale view returns the current (existing) version of the data in the view index, if it exists. The current state of the view index might be different on different nodes in the cluster.

Sorting Returned Rows

Example of requesting the last five records by reversing the sort order:

GET /<database>/_design/<design-doc>/_view/by_title?limit=5&descending=true HTTP/1.1
Accept: application/json
Content-Type: application/json

Example response:

{
   "offset" : 0,
   "rows" : [
      {
         "id" : "Zucchiniinagrodolcesweet-sourcourgettes",
         "key" : "Zucchini in agrodolce (sweet-sour courgettes)",
         "value" : [
            null,
            "Zucchini in agrodolce (sweet-sour courgettes)"
         ]
      },
      {
         "id" : "Zingylemontart",
         "key" : "Zingy lemon tart",
         "value" : [
            null,
            "Zingy lemon tart"
         ]
      },
      {
         "id" : "Zestyseafoodavocado",
         "key" : "Zesty seafood avocado",
         "value" : [
            null,
            "Zesty seafood avocado"
         ]
      },
      {
         "id" : "Zabaglione",
         "key" : "Zabaglione",
         "value" : [
            null,
            "Zabaglione"
         ]
      },
      {
         "id" : "Yogurtraita",
         "key" : "Yogurt raita",
         "value" : [
            null,
            "Yogurt raita"
         ]
      }
   ],
   "total_rows" : 2667
}

The data returned by a view query is in the form of an array. Each element within the array is sorted using native UTF-8 sorting. The sort is applied to the key defined in the view function.

The basic order of output is as follows:

Value Order
null First
false
true
Numbers
Text (lowercase)
Text (uppercase)
Arrays (according to the values of each element, using the order given in this table)
Objects (according to the values of keys, in key order using the order given in this table) Last

You can reverse the order of the returned view information by setting the descending query value true.

Specifying Start and End Keys

Example of querying using startkey and endkey query arguments:

GET /recipes/_design/recipes/_view/by_ingredient?startkey=%22alpha%22&endkey=%22beta%22 HTTP/1.1
Accept: application/json
Content-Type: application/json

The startkey and endkey query arguments can be used to specify the range of values to be displayed when querying the view.

The sort direction is always applied first. Next, filtering is applied using the startkey and endkey query arguments. This means that it is possible to have empty view results because the sorting and filtering do not make sense in combination.

Reversing the order of start and end key will not yield any results:

GET /recipes/_design/recipes/_view/by_ingredient?descending=true&startkey=%22beta%22&endkey=%22alpha%22 HTTP/1.1
Accept: application/json
Content-Type: application/json

For example, if you have a database that returns ten results when viewing with a startkey of “alpha” and an endkey of “beta”, you would get no results when reversing the order. The reason is that the entries in the view are reversed before the key filter is applied.

The view request returns no entries, because “alpha” is alphabetically before “beta”. The returned result is empty:

{
   "total_rows" : 26453,
   "rows" : [],
   "offset" : 21882
}

Therefore the endkey of “beta” is seen before the startkey of “alpha”, resulting in an empty list.

Example of correct filtering and reversing the order of output by using the descending query argument, and reversing the startkey and endkey query arguments:

GET /recipes/_design/recipes/_view/by_ingredient?descending=true&startkey=%22egg%22&endkey=%22carrots%22 HTTP/1.1
Accept: application/json
Content-Type: application/json

The solution is to reverse not just the sort order, but also the startkey and endkey parameter values.

Querying a view using a list of keys

Example request to return all recipes, where the key for the view matches either “clear apple juice” or “lemonade”:

POST /$DB/_design/$DDOC/_view/$VIEWNAME HTTP/1.1
Content-Type: application/json
curl -X POST "https://$USERNAME:$PASSWORD@$USERNAME.cloudant.com/$DB/_design/$DDOC/_view/$VIEWNAME" -d @request.json
{
   "keys" : [
      "some-key",
      "some-other-key"
   ]
}

This method of requesting information from a database executes the specified view-name from the specified design-doc design document. Like the keys parameter for the GET method, the POST method allows you to specify the keys to use when retrieving the view results. In all other aspects, the POST method is identical to the GET API request, in particular, you can use any of its query parameters.

The response contains the standard view information, but only where the keys match:

Example returned view data

{
   "total_rows" : 26484,
   "rows" : [
      {
         "value" : [
            "Scotch collops"
         ],
         "id" : "Scotchcollops",
         "key" : "claret"
      },
      {
         "value" : [
            "Stand pie"
         ],
         "id" : "Standpie",
         "key" : "clear apple juice"
      }
   ],
   "offset" : 6324
}

Multi-document Fetching

Example request to obtain the full documents that match the listed keys:

POST /recipes/_design/recipes/_view/by_ingredient?include_docs=true HTTP/1.1
Content-Type: application/json

{
   "keys" : [
      "claret",
      "clear apple juice"
   ]
}

Example response, returning the full document for each recipe:

{
   "offset" : 6324,
   "rows" : [
      {
         "doc" : {
            "_id" : "Scotchcollops",
            "_rev" : "1-bcbdf724f8544c89697a1cbc4b9f0178",
            "cooktime" : "8",
            "ingredients" : [
               {
                  "ingredient" : "onion",
                  "ingredtext" : "onion, peeled and chopped",
                  "meastext" : "1"
               },
            ...
            ],
            "keywords" : [
               "cook method.hob, oven, grill@hob",
               "diet@wheat-free",
               "diet@peanut-free",
               "special collections@classic recipe",
               "cuisine@british traditional",
               "diet@corn-free",
               "diet@citrus-free",
               "special collections@very easy",
               "diet@shellfish-free",
               "main ingredient@meat",
               "occasion@christmas",
               "meal type@main",
               "diet@egg-free",
               "diet@gluten-free"
            ],
            "preptime" : "10",
            "servings" : "4",
            "subtitle" : "This recipe comes from an old recipe book of 1683 called 'The Gentlewoman's Kitchen'. This is an excellent way of making a rich and full-flavoured meat dish in a very short time.",
            "title" : "Scotch collops",
            "totaltime" : "18"
         },
         "id" : "Scotchcollops",
         "key" : "claret",
         "value" : [
            "Scotch collops"
         ]
      },
      {
         "doc" : {
            "_id" : "Standpie",
            "_rev" : "1-bff6edf3ca2474a243023f2dad432a5a",
            "cooktime" : "92",
            "ingredients" : [
...            ],
            "keywords" : [
               "diet@dairy-free",
               "diet@peanut-free",
               "special collections@classic recipe",
               "cuisine@british traditional",
               "diet@corn-free",
               "diet@citrus-free",
               "occasion@buffet party",
               "diet@shellfish-free",
               "occasion@picnic",
               "special collections@lunchbox",
               "main ingredient@meat",
               "convenience@serve with salad for complete meal",
               "meal type@main",
               "cook method.hob, oven, grill@hob / oven",
               "diet@cow dairy-free"
            ],
            "preptime" : "30",
            "servings" : "6",
            "subtitle" : "Serve this pie with pickled vegetables and potato salad.",
            "title" : "Stand pie",
            "totaltime" : "437"
         },
         "id" : "Standpie",
         "key" : "clear apple juice",
         "value" : [
            "Stand pie"
         ]
      }
   ],
   "total_rows" : 26484
}

Combining a POST request to a given view, with the include_docs=true query argument, enables you to retrieve multiple documents from a database. This technique is more efficient than using multiple GET API requests. However, include_docs=true adds a slight overhead compared to accessing the view on its own.

Sending several queries to a view

Example request:

POST /$DB/_design/$DESIGNDOC/_view/$VIEW HTTP/1.1
Content-Type: application/json
curl https://$USERNAME:$PASSWORD@$USERNAME.cloudant.com/$DB/_design/$DESIGNDOC/_view/$VIEW -H 'Content-Type: application/json' -d @request-body.json
# where request-body.json is a file containing the following JSON data:
{
  "queries": [{

  }, {
    "startkey": 1,
    "limit": 2
  }]
}

Example response:

{
  "results": [
        {
          "total_rows": 3,
          "offset": 0,
          "rows": [
                {
                  "id": "8fbb1250-6908-42e0-8862-aef60dc430a2",
                  "key": 0,
                  "value": {
                    "_id": "8fbb1250-6908-42e0-8862-aef60dc430a2",
                    "_rev": "1-ad1680946839206b088da5d9ac01e4ef",
                    "foo": 0,
                    "bar": "foo"
                  }
                }, {
                  "id": "d69fb42c-b3b1-4fae-b2ac-55a7453b4e41",
                  "key": 1,
                  "value": {
                    "_id": "d69fb42c-b3b1-4fae-b2ac-55a7453b4e41",
                    "_rev": "1-abb9a4fc9f0f339efbf667ace66ee6a0",
                    "foo": 1,
                    "bar": "bar"
                  }
                }, {
                  "id": "d1fa85cd-cd18-4790-8230-decf99e1f60f",
                  "key": 2,
                  "value": {
                    "_id": "d1fa85cd-cd18-4790-8230-decf99e1f60f",
                    "_rev": "1-d075a71f2d47af7d4f64e4a367160e2a",
                    "foo": 2,
                    "bar": "baz"
                  }
                }
          ]
        }, {
          "total_rows": 3,
          "offset": 1,
          "rows": [
                {
                  "id": "d69fb42c-b3b1-4fae-b2ac-55a7453b4e41",
                  "key": 1,
                  "value": {
                    "_id": "d69fb42c-b3b1-4fae-b2ac-55a7453b4e41",
                    "_rev": "1-abb9a4fc9f0f339efbf667ace66ee6a0",
                    "foo": 1,
                    "bar": "bar"
                  }
                }, {
                  "id": "d1fa85cd-cd18-4790-8230-decf99e1f60f",
                  "key": 2,
                  "value": {
                    "_id": "d1fa85cd-cd18-4790-8230-decf99e1f60f",
                    "_rev": "1-d075a71f2d47af7d4f64e4a367160e2a",
                    "foo": 2,
                    "bar": "baz"
                  }
                }
          ]
    }
  ]
}

To send several view queries in one request, use a POST request to /$DB/_design/$DESIGNDOC/_view/$VIEW. The request body is a JSON object containing only the queries field. It holds an array of query objects with fields for the parameters of the query. The field names and their meaning are the same as the query parameters of a regular view request.

The JSON object returned in the response contains only the results field, which holds an array of result objects - one for each query. Each result object contains the same fields as the response to a regular view request.

Example design document:

{
  "_id": "_design/search_example",
  "indexes": {
    "animals": {
      "index": "function(doc){ ... }"
    }
  }
}

Search indexes, defined in design documents, allow databases to be queried using Lucene Query Parser Syntax. Search indexes are defined by an index function, similar to a map function in MapReduce views. The index function decides what data to index and store in the index.

Index functions

Example search index function (see also index guard clauses):

function(doc){
  index("default", doc._id);
  if (doc.min_length){
    index("min_length", doc.min_length, {"store": "true"});
  }
  if (doc.diet){
    index("diet", doc.diet, {"store": "true"});
  }
  if (doc.latin_name){
    index("latin_name", doc.latin_name, {"store": "true"});
  }
  if (doc.class){
    index("class", doc.class, {"store": "true"});
  }
}

The function contained in the index field is a Javascript function that is called for each document in the database. It takes the document as a parameter, extracts some data from it and then calls the index function to index that data.

The index function takes three parameters, where the third parameter is optional. The first parameter is the name of the field used when querying the index, specified in the Lucene syntax portion of the query. For example, when querying:

q=color:red

“color” is the Lucene field name.

If the special value "default" is used, the field name is not specified at query time. The effect is that the query becomes:

q=red

The second parameter is the data to be indexed. The third parameter is an object that can contain the fields store and index. If the store field contains the value true, the value will be returned in search results, otherwise, it will only be indexed.

The index function also provides a third ‘options’ parameter that receives a JavaScript Object with the following possible values and defaults:

Option Description Values Default
index Whether the data is indexed, and if so, how. If set to false, the data cannot be used for searches, but can still be retrieved from the index if store is set to true. See Analyzers for more information. analyzed, analyzed_no_norms, no, not_analyzed, not_analyzed_no_norms analyzed
facet Creates a faceted index. See Faceting for more information. true, false false
store If true, the value is returned in the search result; otherwise, the value is not returned. true, false false

Index Guard Clauses

Example of failing to check if the index data field exists:

if (doc.min_length) {
  index("min_length", doc.min_length, {"store": "true"});
}

The index function requires the name of the data field to index as the second parameter. However, if that data field does not exist for the document, an error occurs. The solution is to use an appropriate ‘guard clause’ that checks if the field exists, and contains the expected type of data, before attempting to create the corresponding index.

Using a guard clause to check if the required data field exists, and holds a number, before attempting to index:

if (typeof(doc.min_length) === 'number') {
  index("min_length", doc.min_length, {"store": "true"});
}

You might use the javascript typeof function to perform the guard clause test. If the field exists and has the expected type, the correct type name is returned, so the guard clause test succeeds and it is safe to use the index function. If the field does not exist, you would not get back the expected type of the field, therefore you would not attempt to index the field.

Whatever guard clause test you decide to use, remember that Javascript considers a result to be false if one of the following values is tested:

A ‘generic’ guard clause:

if (typeof(doc.min_length) !== 'undefined') {
  // The field exists, and does have a type, so we can proceed to index using it.
  ...
}

Therefore, a possible generic guard clause simply tests to ensure that the type of the candidate data field is defined.

Analyzers

Example analyzer document:

{
  "_id": "_design/analyzer_example",
  "indexes": {
    "INDEX_NAME": {
      "index": "function (doc) { ... }",
      "analyzer": "$ANALYZER_NAME"
    }
  }
}

Analyzers are settings which define how to recognize terms within text. This can be helpful if you need to index multiple languages.

Here’s the list of generic analyzers supported by Cloudant search:

Analyzer Description
classic The standard Lucene analyzer, circa release 3.1. You’ll know if you need it.
email Like the standard analyzer, but tries harder to match an email address as a complete token.
keyword Input is not tokenized at all.
simple Divides text at non-letters.
standard The default analyzer. It implements the Word Break rules from the Unicode Text Segmentation algorithm.
whitespace Divides text at whitespace boundaries.

Language-Specific Analyzers

These analyzers will omit very common words in the specific language, and many also remove prefixes and suffixes. The name of the language is also the name of the analyzer.

Per-Field Analyzers

Example of defining different analyzers for different fields:

{
  "_id": "_design/analyzer_example",
  "indexes": {
    "INDEX_NAME": {
      "analyzer": {
        "name": "perfield",
        "default": "english",
        "fields": {
          "spanish": "spanish",
          "german": "german"
        }
      },
      "index": "function (doc) { ... }"
    }
  }
}

The perfield analyzer configures multiple analyzers for different fields.

Stop Words

Example of defining non-indexed (‘stop’) words:

{
  "_id": "_design/stop_words_example",
  "indexes": {
    "INDEX_NAME": {
      "analyzer": {
        "name": "portuguese",
        "stopwords": [
          "foo", 
          "bar", 
          "baz"
        ]
      },
      "index": "function (doc) { ... }"
    }
  }
}

Stop words are words that do not get indexed. You define them within a design document by turning the analyzer string into an object.

Testing analyzer tokenization

Example test of the keyword analyzer

curl 'https://<account>.cloudant.com/_search_analyze' -H 'Content-Type: application/json'
  -d '{"analyzer":"keyword", "text":"ablanks@renovations.com"}'
Host: <account>.cloudant.com
POST /_search_analyze HTTP/1.1
Content-Type: application/json
{"analyzer":"keyword", "text":"ablanks@renovations.com"}

Result of testing the keyword analyzer

{
  "tokens": [
    "ablanks@renovations.com"
  ]
}

Example test of the standard analyzer

curl 'https://<account>.cloudant.com/_search_analyze' -H 'Content-Type: application/json'
  -d '{"analyzer":"standard", "text":"ablanks@renovations.com"}'
Host: <account>.cloudant.com
POST /_search_analyze HTTP/1.1
Content-Type: application/json
{"analyzer":"standard", "text":"ablanks@renovations.com"}

Result of testing the standard analyzer

{
  "tokens": [
    "ablanks",
    "renovations.com"
  ]
}

You can test the results of analyzer tokenization by posting sample data to the _search_analyze endpoint.

Queries

curl https://$USERNAME.cloudant.com/$DATABASE/$DESIGN_ID/_search/$INDEX_NAME?q=$QUERY \
     -u $USERNAME
var nano = require('nano');
var account = nano("https://"+$USERNAME+":"+$PASSWORD+"@"+$USERNAME+".cloudant.com");
var db = account.use($DATABASE);

db.search($DESIGN_ID, $SEARCH_INDEX, {
  q: $QUERY
}, function (err, body, headers) {
  if (!err) {
    console.log(body);
  }
});

Once you’ve got an index written, you can query it with a GET request to https://$USERNAME.cloudant.com/$DATABASE/$DESIGN_ID/_search/$INDEX_NAME. Specify your search query in the query query parameter.

Query Parameters

Argument Description Optional Type Supported Values
bookmark A bookmark that was received from a previous search. This allows you to page through the results. If there are no more results after the bookmark, you will get a response with an empty rows array and the same bookmark. That way you can determine that you have reached the end of the result list. yes string
counts This field defines an array of names of string fields, for which counts should be produced. The response will contain counts for each unique value of this field name among the documents matching the search query. yes JSON A JSON array of field names
drilldown This field can be used several times. Each use defines a pair of a field name and a value. The search will only match documents that have the given value in the field name. It differs from using "fieldname:value" in the q parameter only in that the values are not analyzed. yes JSON A JSON array with two elements, the field name and the value.
group_field Field by which to group search matches. yes String A string containing the field name and optionally the type of the field (string or number) in angle brackets. If the type is not specified, it defaults to string. For example, age<number>.
group_limit Maximum group count. This field can only be used if group_field is specified. yes Numeric
group_sort This field defines the order of the groups in a search using group_field. The default sort order is relevance. yes JSON This field can have the same values as the sort field, so single fields as well as arrays of fields are supported.
include_docs Include the full content of the documents in the response yes boolean
limit Limit the number of the returned documents to the specified number. In case of a grouped search, this parameter limits the number of documents per group. yes numeric The limit value can be any positive integer number up to and including 200.
query A Lucene query no string or number
ranges This field defines ranges for faceted, numeric search fields. The value is a JSON object where the fields names are numeric, faceted search fields and the values of the fields are again JSON objects. Their field names are names for ranges. The values are Strings describing the range, for example "[0 TO 10]" yes JSON The value must be on object whose fields again have objects as their values. These objects must have string describing ranges as their field values.
sort Specifies the sort order of the results. In a grouped search (i.e. when group_field is used), this specifies the sort order within a group. The default sort order is relevance. yes JSON A JSON string of the form "fieldname<type>" or -fieldname<type> for descending order, where fieldname is the name of a string or number field and type is either number or string or a JSON array of such strings. The type part is optional and defaults to number. Some examples are "foo", "-foo", "bar<string>", "-foo<number>" and ["-foo<number>", "bar<string>"]. String fields used for sorting must not be analyzed fields. The field(s) used for sorting must be indexed by the same indexer used for the search query.
stale Don’t wait for the index to finish building to return results. yes string ok

Query Syntax

Example search query:

// Birds
class:bird
// Animals that begin with the letter "l"
l*
// Carnivorous birds
class:bird AND diet:carnivore
// Herbivores that start with letter
"l" l* AND diet:herbivore
// Medium-sized herbivores 
min_length:[1 TO 3] AND diet:herbivore
// Herbivores that are 2m long or less 
diet:herbivore AND min_length:[-Infinity TO 2]
// Mammals that are at least 1.5m long 
class:mammal AND min_length:[1.5 TO Infinity]
// Find "Meles meles"
latin_name:"Meles meles"
// Mammals who are herbivore or carnivore
diet:(herbivore OR omnivore) AND class:mammal

The Cloudant search query syntax is based on the Lucene syntax. Search queries take the form of name:value (unless the name is omitted, in which case they hit the default field, demonstrated in the example to your right).

Queries over multiple fields can be logically combined, and groups and fields can be further grouped. The available logical operators are case sensitive and are AND, +, OR, NOT and -. Range queries can run over strings or numbers.

If you want a fuzzy search you can run a query with ~ to find terms like the search term. For instance, look~ will find terms book and took.

You can alter the importance of a search term by adding ^ + a positive number. This makes matches containing the term more or less relevant to the power of the boost value, with 1 as the default. Any decimal between 0 and 1 will reduce importance while anything over 1 will increase it.

Wild card searches are supported, for both single (?) and multiple (*) character searches. dat? would match date and data, dat* would match date, data, database, dates etc. Wildcards must come after the search term.

Result sets from searches are limited to 200 rows, and return 25 rows by default. The number of rows returned can be changed via the limit parameter. The response contains a bookmark. If the bookmark is passed back as a URL parameter you’ll skip through the rows you’ve already seen and get the next set of results.

The following characters require escaping if you want to search on them: + - && || ! ( ) { } [ ] ^ " ~ * ? : \ /

Escape these with a preceding backslash character.

Faceting

Example search query, specifying that faceted search is enabled:

function(doc) {
  index("type", doc.type, {"facet": true});
  index("price", doc.price, {"facet": true});
}

Example of ranges faceted search:

?q=*:*&ranges={"price":{"cheap":"[0 TO 100]","expensive":"{100 TO Infinity}"}}

Example results for faceted search ranges example:

{
  "total_rows":100000,
  "bookmark":"g...",
  "rows":[...],
  "ranges": {
    "price": {
      "expensive": 278682,
      "cheap": 257023
    }
  }
}

Cloudant Search also supports faceted searching, which allows you to discover aggregate information about all your matches quickly and easily. You can match all documents using the special ?q=*:* query syntax, and use the returned facets to refine your query. To indicate a field should be indexed for faceted queries, set {"facet": true} in its options.

Counts

Example query

?q=*:*&counts=["type"]

Example response

{
  "total_rows":100000,
  "bookmark":"g...",
  "rows":[...],
  "counts":{
    "type":{
      "sofa": 10, 
      "chair": 100,
      "lamp": 97
    }
  }
}

The count facet syntax takes a list of fields, and returns the number of query results for each unique value of each named field.

Ranges

Example query

?q=*:*&ranges={"price":{"cheap":"[0 TO 100]","expensive":"{100 TO Infinity}"}}

Example response

{
  "total_rows":100000,
  "bookmark":"g...",
  "rows":[...],
  "ranges": {
    "price": {
      "expensive": 278682,
      "cheap": 257023
    }
  }
}

The range facet syntax reuses the standard Lucene syntax for ranges to return counts of results which fit into each specified category. Inclusive range queries are denoted by square brackets ([, ]). Exclusive range queries are denoted by curly brackets ({, }).

Geographical searches

Some example data…

{
    "name":"Aberdeen, Scotland",
    "lat":57.15,
    "lon":-2.15,
    "type":"city"
}

… as well as a design document with a search index for them.

function(doc) {
    if (doc.type && doc.type == 'city') {
        index('city', doc.name, {'store': true});
        index('lat', doc.lat, {'store': true});
        index('lon', doc.lon, {'store': true});
    }
}

An example query that sorts cities in the upper hemisphere by their distance to New York:

curl 'https://docs.cloudant.com/examples/_design/cities-designdoc/_search/cities?q=lat:[0+TO+90]&sort="<distance,lon,lat,-74.0059,40.7127,km>"'
GET /examples/_design/cities-designdoc/_search/cities?q=lat:[0+TO+90]&sort="<distance,lon,lat,-74.0059,40.7127,km>" HTTP/1.1
Host: docs.cloudant.com

Example response

{
    "total_rows": 205,
    "bookmark": "g1AAAAEbeJzLYWBgYMlgTmGQS0lKzi9KdUhJMtfLTczJLyrRS87JL01JzCvRy0styQGqY0pkSLL___9_Fpjj5tDCOG974NGNieJZqAaY4DQgyQFIJtUjmyHXJivfY5PIgmaGKU4z8liAJEMDkAIasx9mTnPNv-PSgosTmbOI9QzEnAMQc-DuqY3U-vbZXTSRNSsLAMMnXIU",
    "rows": [
        {
            "id": "city180",
            "order": [
                8.530665755719783,
                18
            ],
            "fields": {
                "city": "New York, N.Y.",
                "lat": 40.78333333333333,
                "lon": -73.96666666666667
            }
        },
        {
            "id": "city177",
            "order": [
                13.756343205985946,
                17
            ],
            "fields": {
                "city": "Newark, N.J.",
                "lat": 40.733333333333334,
                "lon": -74.16666666666667
            }
        },
        {
            "id": "city178",
            "order": [
                113.53603438866077,
                26
            ],
            "fields": {
                "city": "New Haven, Conn.",
                "lat": 41.31666666666667,
                "lon": -72.91666666666667
            }
        }
    ]
}

In addition to searching by the content of textual fields, you can also sort your results by their distance from a geographic coordinate.

You will need to index two numeric fields (representing the longitude and latitude).

You can then query using the special sort field which takes 5 parameters:

You can combine sorting by distance with any other search query, such as range searches on the latitude and longitude or queries involving non-geographical information. That way, you can search in a bounding box and narrow down the search with additional criteria.

Cloudant Geospatial

Cloudant Geospatial, or ‘Cloudant Geo’, combines the advanced geospatial queries of a Geographic Information System (GIS) with the flexibility and scalability of Cloudant’s database-as-a-service (DBaaS) capabilities.

Cloudant Geo:

Cloudant Geo overview

Cloudant Geo lets you structure your data using GeoJSON_ format. Design documents are used to index the data. Just like working with other Cloudant documents, an initial scan works through all the documents in the database, giving you the first index. Subsequent updates to the documents result in incremental updates to the index.

The key advantage of Cloudant Geo is to enable you to identify, specify, or search for documents based on a spatial relationship; in effect using geometry to provide an additional way of expressing the relationship between and within documents.

Example of relation using a geospatial polygon:

relation=contains&g=POLYGON ((-71.0537124 42.3681995 0,-71.054399 42.3675178 0,-71.0522962 42.3667409 0,-71.051631 42.3659324 0,-71.051631 42.3621431 0,-71.0502148 42.3618577 0,-71.0505152 42.3660275 0,-71.0511589 42.3670263 0,-71.0537124 42.3681995 0))

An example would be to specify that a document is considered to be ‘contained’ if it has a geospatial characteristic that fits within a given geospatial polygon, defined by a series of points.

The basic steps for working with geospatial data in Cloudant Geo is as follows:

  1. Include a GeoJSON_ geometry object in your JSON document. The geometry object can be of any type, including points, lines, or polygons.
  2. Index the geometry object using st_index.
  3. Work with the data by querying using various geometries and geometric relationships.

GeoJSON

GeoJSON format data is used to express a variety of geographic data structures, including:

A GeoJSON document is simply a JSON document containing three distinct key:value sections:

type

This is a simple key:value pair. It must be present, and must contain the value Feature.

geometry

This section must contain two fields.

The type field holds a GeoJSON object value such as Point, LineString or Polygon.

The coordinates field holds an array of latitude and longitude values.

properties

This section holds any other data you wish to store in the GeoJSON document. It is not required by Cloudant Geo.

Example GeoJSON document:

{
  "_id": "79f14b64c57461584b152123e38a6449",
  "_rev": "1-e6b5ca2cd8047747ca07cf36d290a4c8",
  "geometry": {
    "coordinates": [
  -71.13687953,
  42.34690635
    ],
    "type": "Point"
  },
  "properties": {
    "compnos": "142035014",
    "domestic": false,
    "fromdate": 1412209800000,
    "main_crimecode": "MedAssist",
    "naturecode": "EDP",
    "reptdistrict": "D14",
    "shooting": false,
    "source": "boston"
  },
  "type": "Feature"
}

More information about GeoJSON, including the full specification, is available at http://geojson.org/.

Creating a Cloudant GEO Index

To make it easier to work with Cloudant Geo documents, it is best practice to create a separate design document, specifically for Cloudant Geo. For example, you could create a design document with the _id value "_design/geodd".

Within that design document, you create an object called st_indexes to hold one or more Cloudant Geo index definitions.

geoidx: An example Cloudant Geo index

Example Cloudant Geo design document, containing an index:

{
  "_id": "_design/geodd",
  "views": {},
  "language": "javascript",
  "st_indexes": {
    "geoidx": {
  "index": "function(doc) {
      if (doc.geometry && doc.geometry.coordinates) {
        st_index(doc.geometry);
      }
    }"
    }
  }
}

For example, you might create a Cloudant Geo design document containing an index called geoidx. The index is a simple Javascript function that checks for the presence of a valid geometry object in the document, and if found ensures that the document is included in the st_index Cloudant Geo index.

Geospatial indexing

There are a number of different algorithms for indexing geospatial data. Some are simple to understand and implement, but are not fast at producing results.

The algorithm used by Cloudant Geo is R*_tree. Although it has a slightly higher resource requirement for building the index, the resulting index offers much better performance in responding to queries.

Querying a Cloudant Geo index

The basic format for a Cloudant Geo API call:

/<database>/_design/<name>/_geo/<geoindexname>?<query-parameters>

The fundamental API call for utilizing Cloudant Geo has a simple format.

The valid <query-parameters> are as follows:

Parameter Description
bookmark Allows you to page through the results. The default is 25 results.
ellipse Used in a query. Specify a latitude, a longitude, and two radii: rangex and rangey. The distance is measured in meters.
g Used in a query. Specify a geometry value g. Requires a geometric relationship relation.
include_docs Add the entire document as a document object, and include it in the output results.
limit An integer to limit the number of results returned. The default is 100. The maximum is 200. A value larger than 200 is an error.
radius Query. Specify a latitude, a longitude, and a radius. The distance is measured in meters.
relation Used in a query. Specify a geometric relationship. Used in conjunction with ellipse, g, or radius parameters.
stale=ok Speed up responses by not waiting for index building or update to complete.

Geospatial relationships

Cloudant Geo works with geospatial relationships. These define the different ways in which two geospatial objects are connected with each other, if indeed they are connected at all. For example, if you and a colleague live in different towns, there is no geospatial connection. However, if you live on different streets within the same town, then at the town level there is a connection, but not at the street level.

Cloudant Geo supports the following standard geospatial relationships, applied to two distinct geospatial objects A and B:

Relation Description
bbox A envelope True if the geometry of A is entirely within the envelope specified in the relation.
A contains B True if the geometry of B is entirely within the geometry of A.
A crosses B
True if:
  • The intersection of the two geometries is a value with dimensions within that of the two geometries, and
  • The maximum dimension of the intersection value includes points that are within both the geometries, and
  • The intersection value is not equal to either of the two geometries.
A disjoint B True if the two geometries do not touch or intersect.
A equals B True if the two geometries are the same.
A intersects B True if the two geometries intersect.
A overlaps B
True if:
  • The two geometries have some, but not all, points in common, and
  • The points in common form the same kind of shape as A and B, for example a polygon.
A touches B True if and only if the common points of the two geometries are found only at the boundaries of the geometries.
A within B True if all the points of A lie entirely within the geometry of B.

Geometries

Cloudant Geo describes geometries using the g query parameter. The geometry can be any ‘Well Known Text’ (WKT) or ‘Well Know Binary’ (WKB) object. You can then specify the relationship you want to use when querying the documents in your database. For example, you might specify a polygon object that describes a housing district. You could then query your document database for people residing within that district, by requesting all documents where the place of residence is contained within the polygon object.

Example of a point object:

point(-71.0537124 42.3681995)

Example of a polygon object:

polygon((-71.0537124 42.3681995 0,-71.054399 42.3675178 0,-71.0522962 42.3667409 0,-71.051631 42.3659324 0,-71.051631 42.3621431 0,-71.0502148 42.3618577 0,-71.0505152 42.3660275 0,-71.0511589 42.3670263 0,-71.0537124 42.3681995 0))

There are several standard geometric objects, including:

Example: Querying a Cloudant Geo index

Simple circle

Example query to find documents that have a geospatial position within a circle:

https://sampleac.cloudant.com/sampledb/_design/geodd/_geo/geoidx
?radius=10
&lon=-71.07959
&lat=42.3397
&relation=contains

Example response to the query:

{
  "bookmark": "g2wAAAABaA....  ...lS19_ztq",
  "type": "FeatureCollection",
  "features": [
    {
  "id": "79f14b64c57461584b152123e38a8e8b",
  "geometry": {
    "type": "Point",
    "coordinates": [-71.07958956,42.33967135]
  },
  "properties": {}
    }
  ]
}

An example of using Cloudant Geo would be to find documents that are considered to have a geospatial position within a given geographic circle. This might be useful to determine insurance customers who live close to a known flood plain.

To specify the circle, you would provide:

The query would then compare the geometry of each document in the index with the specified circle. The comparison is performed according the relation you request in the query. So, to find all documents that fall within the circle, you would use the relation contains.

A polygon query

A more complex example is where you specify a polygon as the geomtric object of interest. A polygon is simply any object defined by a series of connected points, where none of the connections (the lines between the points) cross any of the other connections.

Example query to find documents that have a geospatial position within a polygon:

https://sampleac.cloudant.com/sampledb/_design/geodd/_geo/geoidx
?relation=overlaps
&g=POLYGON ((-71.0537124 42.3681995 0,-71.054399 42.3675178 0,-71.0522962 42.3667409 0,-71.051631 42.3659324 0,-71.051631 42.3621431 0,-71.0502148 42.3618577 0,-71.0505152 42.3660275 0,-71.0511589 42.3670263 0,-71.0537124 42.3681995 0))

Example response to the query:

{
  "bookmark": "g2wAAAABaA... ...L5zTjZq",
  "type": "FeatureCollection",
  "features": [
    {
  "id": "79f14b64c57461584b152123e38d6349",
  "geometry": {
    "type": "Point",
    "coordinates": [-71.05107956,42.36510634]
  },
  "properties": {}
    },
    {
  "id": "79f14b64c57461584b152123e3924516",
  "geometry": {
    "type": "Point",
    "coordinates": [-71.05204477,42.36674199]
  },
  "properties": {}
    }
  ]
}

As an example, we might provide a polygon description as the geometric object, and then request that the query return details of documents within the database that overlap with the polygon.

Replication

Cloudant replication is the process that synchronizes (‘syncs’) the state of two databases. Any change which has occured in the source database is reproduced in the target database. You can create replications between any number of databases, whether continuous or not.

Depending on your application requirements, you use replication to share and aggregate state and content.

This overview explains how replication works:

Replication takes place in one direction only. To keep two databases synchronized with each other, you must replicate in both directions. This means that you must replicate from databasea to databaseb, and separately from databaseb to databasea.

Replications are created in one of two ways:

  1. A replication can be created using a replication document in the _replicator database. Creating and modifying replications in this way allows you to control replication in the same as working with other documents.
  2. A replication can be started by POSTing a JSON document describing the desired replication directly to the /_replicate endpoint.

Replication document format

The format of the document used to describe a replication is as follows:

Field Name Required Description
source yes Identifies the database to copy revisions from. Can be a database URL, or an object whose url property contains the full URL of the database.
target yes Identifies the database to copy revisions to. Same format and interpretation as source. Does not have to be the same value as the source field.
continuous no Continuously syncs state from the source to the target, only stopping when deleted.
create_target no A value of true tells the replicator to create the target database if it does not exist.
doc_ids no Array of document IDs; if given, only these documents are replicated.
filter no Name of a filter function that can choose which documents get replicated.
proxy no Proxy server URL.
query_params no Object containing properties that are passed to the filter function.
use_checkpoints
no Indicate whether to create checkpoints. Checkpoints greatly reduce the time and resources needed for repeated replications. Setting this to false removes the requirement for write access to the source database. Defaults to true.
user_ctx no An object containing the username and optionally an array of roles, e.g.: "user_ctx": {"name": "jane", "roles": ["admin"]}. This is needed for the replication to show up in the output of /_active_tasks.

The /_replicator database

The /_replicator database is a special database where you can PUT or POST documents to trigger replications, or DELETE to cancel ongoing replications. These documents have exactly the same content as the JSON documents you can POST to the /_replicate/ endpoint. The fields supplied in the replication document are source, target, continuous, create_target, doc_ids, filter, proxy, query_params, use_checkpoints. These fields are described in the Replication document format.

Replication documents can have a user defined _id.

The names of the source and target databases do not have to be the same.

Creating a replication

Example instructions for creating a replication document:

curl -X PUT https://$USERNAME:$PASSWORD@USERNAME.cloudant.com/_replicator/replication-doc -H 'Content-Type: application/json' -d @replication-document.json
#assuming replication-document.json is a json file with the following content:
PUT /_replicator/replication-doc HTTP/1.1
Content-Type: application/json

Example replication document:

{
  "source": "https://$USERNAME1:$PASSWORD1@$USERNAME1.cloudant.com/$DATABASE1",
  "target": "https://$USERNAME2:$PASSWORD2@$USERNAME2.cloudant.com/$DATABASE2",
  "create_target": true,
  "continuous": true
}

To start a replication, add a replication document to the _replicator database.

This overview explains how to create a replication job:

You can set up replication using cURL:

Monitoring a replication

Example instructions for monitoring a replication:

curl https://$USERNAME:$PASSWORD@$USERNAME.cloudant.com/_active_tasks
GET /_active_tasks HTTP/1.1
var nano = require('nano');
var account = nano("https://"+$USERNAME+":"+$PASSWORD+"@"+$USERNAME+".cloudant.com");

account.request({
  path: '_active_tasks'
}, function (err, body, headers) {
  if (!err) {
    console.log(body.filter(function (task) {
      return (task.type === 'replication');
    })); 
  }
});

Example response of active task including continuous replication:

[
  {
    "user": null,
    "updated_on": 1363274088,
    "type": "replication",
    "target": "https://repl:*****@tsm.cloudant.com/user-3dglstqg8aq0uunzimv4uiimy/",
    "docs_read": 0,
    "doc_write_failures": 0,
    "doc_id": "tsm-admin__to__user-3dglstqg8aq0uunzimv4uiimy",
    "continuous": true,
    "checkpointed_source_seq": "403-g1AAAADfeJzLYWBgYMlgTmGQS0lKzi9KdUhJMjTRyyrNSS3QS87JL01JzCvRy0styQGqY0pkSLL___9_VmIymg5TXDqSHIBkUj1YUxyaJkNcmvJYgCRDA5AC6tuflZhGrPsgGg9ANAJtzMkCAPFSStc",
    "changes_pending": 134,
    "pid": "<0.1781.4101>",
    "node": "dbcore@db11.julep.cloudant.net",
    "docs_written": 0,
    "missing_revisions_found": 0,
    "replication_id": "d0cdbfee50a80fd43e83a9f62ea650ad+continuous",
    "revisions_checked": 0,
    "source": "https://repl:*****@tsm.cloudant.com/tsm-admin/",
    "source_seq": "537-g1AAAADfeJzLYWBgYMlgTmGQS0lKzi9KdUhJMjTUyyrNSS3QS87JL01JzCvRy0styQGqY0pkSLL___9_VmI9mg4jXDqSHIBkUj1WTTityWMBkgwNQAqob39WYhextkE0HoBoBNo4MQsAFuVLVQ",
    "started_on": 1363274083
  }
]

Example response of active task including single replication:

[
  {
    "pid": "<0.1303.0>",
    "replication_id": "e42a443f5d08375c8c7a1c3af60518fb+create_target",
    "checkpointed_source_seq": 17333,
    "continuous": false,
    "doc_write_failures": 0,
    "docs_read": 17833,
    "docs_written": 17833,
    "missing_revisions_found": 17833,
    "progress": 3,
    "revisions_checked": 17833,
    "source": "http://username.cloudant.com/db/",
    "source_seq": 551202,
    "started_on": 1316229471,
    "target": "test_db",
    "type": "replication",
    "updated_on": 1316230082
  }
]

To monitor replicators currently in process, make a GET request to https://$USERNAME.cloudant.com/_active_tasks. This returns any active tasks, including replications. To filter for replications, look for documents with "type": "replication".

This overview explains how to check replication status:

For details about the information provided by _active_tasks, see Active tasks.

Delete

Example instructions for deleting a replication document:

DELETE /_replicator/replication-doc?rev=1-... HTTP/1.1
curl -X DELETE https://$USERNAME:$PASSWORD@$USERNAME.cloudant.com/_replicator/replication-doc?rev=1-...

To cancel a replication, simply delete its replication document from the _replicator database.

If the replication is in an error state, the replicator makes repeated attempts to achieve a successful replication. A consequence is that the replication document is updated with each attempt. This also changes the document revision value. Therefore, you should get the revision value immediately before deleting the document, otherwise you might get an HTTP 409 “document update conflict” response.

The /_replicate endpoint

Example instructions for starting a replication:

curl -H 'Content-Type: application/json' -X POST "https://$USERNAME:$PASSWORD@$USERNAME.cloudant.com/_replicate" -d @replication-doc.json
#with the file replication-doc.json containing the required replication.
POST /_replicate HTTP/1.1
Content-Type: application/json

Example document describing the required replication:

{
  "source": "http://$USERNAME:$PASSWORD@username.cloudant.com/example-database",
  "target": "http://$USERNAME2:$PASSWORD2@example.org/example-target-database"
}

You are encouraged to use the Replicator Database to manage replication. However, replication can also be triggered by sending a POST request directly to the /_replicate API URL. The POST contains a JSON document that describes the desired replication.

Return Codes

Code Description
200 Replication request successfully completed.
202 Continuous replication request has been accepted.
404 Either the source or target database was not found.
500 JSON specification was invalid.

Use this call to request, configure, or stop, a replication operation.

The specification of the replication request is controlled through the JSON content of the request. The JSON should be an object with fields defining the source, target and other options. The fields of the JSON request are as follows:

Replication Operation

Example request to replicate between a database on the source server example.com, and a target database on Cloudant:

POST /_replicate
Content-Type: application/json
Accept: application/json

{
   "source" : "http://user:pass@example.com/db",
   "target" : "http://user:pass@user.cloudant.com/db",
}

Example error reponse if one of the requested databases for a replication does not exist:

{
   "error" : "db_not_found"
   "reason" : "could not open http://username.cloudant.com/ol1ka/",
}

The aim of replication is that at the end of the process, all active documents on the source database are also in the destination or ‘target’ database, and that all documents deleted from the source databases are also deleted from the destination database (if they existed there).

Replication has two forms: push or pull replication:

Pull replication is helpful if your source database has a permanent IP address, and your destination database is local and has a dynamically assigned IP address, for example, obtained through DHCP. Pull replication is especially appropriate if you are replicating to a mobile or other device from a central server.

In all cases, the requested databases in the source and target specification must exist. If they do not, an error is returned within the JSON object.

Creating a target database during replication

Example request to create a target database and replicate onto it:

POST http://username.cloudant.com/_replicate
Content-Type: application/json
Accept: application/json

{
   "create_target" : true
   "source" : "http://user:pass@example.com/db",
   "target" : "http://user:pass@user.cloudant.com/db",
}

If your user credentials allow it, you can create the target database during replication by adding the create_target field to the request object.

The create_target field is not destructive. If the database already exists, the replication proceeds as normal.

Canceling replication

Example instructions for canceling a replication:

curl -H 'Content-Type: application/json' -X POST 'https://$USERNAME:$PASSWORD@$USERNAME.cloudant.com/_replicate HTTP/1.1' -d @replication-doc.json
#the file replication-doc.json has the following content:
POST /_replicate HTTP/1.1
Content-Type: application/json

Example document to describe the replication to be canceled:

{
  "source": "https://username:password@username.cloudant.com/example-database",
  "target": "https://username:password@example.org/example-database",
  "cancel": true
}

A replication triggered by POSTing to /_replicate can be canceled by POSTing the exact same JSON object but with the additional cancel property set to true.

The replication ID can be obtained from the original replication request if it is a continuous replication. Alternatively, the replication ID can be obtained from /_active_tasks.

Single Replication

Example request for a single synchronization between the source database recipes and the target database recipes2.

POST /_replicate
Content-Type: application/json
Accept: application/json

{
   "source" : "http://user:pass@user.cloudant.com/recipes",
   "target" : "http://user:pass@user.cloudant.com/recipes2",
}

Example response following a request for a single replication:

{
   "ok" : true,
   "history" : [
      {
         "docs_read" : 1000,
         "session_id" : "52c2370f5027043d286daca4de247db0",
         "recorded_seq" : 1000,
         "end_last_seq" : 1000,
         "doc_write_failures" : 0,
         "start_time" : "Thu, 28 Oct 2010 10:24:13 GMT",
         "start_last_seq" : 0,
         "end_time" : "Thu, 28 Oct 2010 10:24:14 GMT",
         "missing_checked" : 0,
         "docs_written" : 1000,
         "missing_found" : 1000
      }
   ],
   "session_id" : "52c2370f5027043d286daca4de247db0",
   "source_last_seq" : 1000
}

Replication of a database means that the two databases - the ‘source’ and the ‘target’ - are synchronized. By default, the replication process occurs one time, and synchronizes the two databases together.

The response to a request for a single replication is a JSON structure containing the success or failure status of the synchronization process. The response also contains statistics about the process.

The structure of the response includes details about the replication status:

Continuous Replication

Example instructions for enabling continuous replication:

curl -H 'Content-Type: application/json' -X POST http://$USERNAME:$PASSWORD@$USERNAME.cloudant.com/_replicate -d @replication-doc.json
# where the file replication-doc.json indicates that the replication should be continuous
POST /_replicate HTTP/1.1
Content-Type: application/json

Example document specifying that the replication should be continuous:

{
  "source": "http://username:password@example.com/foo", 
  "target": "http://username:password@username.cloudant.com/bar", 
  "continuous": true
}

By default, the synchronization of a database during replication happens only once, at the time the replicate request is made. To ensure that replication from the source database to the target database takes place continually, set the continuous field of the JSON object within the request to true.

With continuous replication, changes in the source database are replicated to the target database forever, until you specifically cancel the replication.

Changes are replicated between the two databases as long as a network connection is available between the two instances.

When in operation, the replication process does not stop when it has processed all current updates. Instead, the replication process continues to wait for further updates to the source database, and applies them to the target.

Canceling Continuous Replication

Example replication request to create the target database if it does not exist, and to replicate continuously:

{
   "source" : "http://user:pass@example.com/db",
   "target" : "http://user:pass@user.cloudant.com/db",
   "create_target" : true,
   "continuous" : true
}

Example request to cancel the replication, providing matching fields to the original request:

{
    "cancel" : true,
    "continuous" : true
    "create_target" : true,
    "source" : "http://user:pass@example.com/db",
    "target" : "http://user:pass@user.cloudant.com/db",
}

Cancel continuous replication by including the cancel field in the JSON request object, and setting the value to true.

Requesting cancellation of a replication that does not exist results in a 404 error.

Example replication sequence

Example instructions for starting a replication:

$ curl -H 'Content-Type: application/json' -X POST 'http://username.cloudant.com/_replicate' -d @replication-doc.json
#the file replication-doc.json describes the intended replication.
POST /_replicate HTTP/1.1
Content-Type: application/json

Example document describing the intended replication:

{
  "source": "https://username:password@example.com/foo", 
  "target": "https://username:password@username.cloudant.com/bar", 
  "create_target": true, 
  "continuous": true
}

Example response after starting the replication:

{
  "ok": true,
  "_local_id": "0a81b645497e6270611ec3419767a584+continuous+create_target"
}

Example instructions for canceling the replication:

curl -H 'Content-Type: application/json' -X POST http://$USERNAME:$PASSWORD@$USERNAME.cloudant.com/_replicate -d @replication-doc.json
# where the file replication-doc.json specifies the replication task to be canceled.
POST /_replicate HTTP/1.1
Content-Type: application/json

Example document specifying the replication to be canceled:

{
  "replication_id": "0a81b645497e6270611ec3419767a584+continuous+create_target",
  "cancel": true
}

Example response after successfully canceling the replication, indicated by the "ok":true content:

{
  "ok": true,
  "_local_id": "0a81b645497e6270611ec3419767a584+continuous+create_target"
}

A simple example of creating a replication task, then canceling it.

Advanced replication

This section contains details about more advanced replication concepts and tasks.

You might also find it helpful to review details of the underlying replication protocol, as well as reviewing the Advanced Methods material.

Replication Status

Example replication document, PUT into /_replicator:

{
  "_id": "my_rep",
  "source":  "https://username:password@myserver.com:5984/fromthis",
  "target":  "https://username:password@username.cloudant.com/tothat",
  "create_target":  true
}

Example of automatic document update once replication starts:

{
  "_id": "my_rep",
  "source":  "https://username:password@myserver.com:5984/fromthis",
  "target":  "https://username:password@username.cloudant.com/tothat",
  "create_target":  true
  "_replication_id":  "c0ebe9256695ff083347cbf95f93e280",
  "_replication_state":  "triggered",
  "_replication_state_time":  "2011-06-07T16:54:35+01:00"
}

When replication is managed by storing a document in the /_replicator database, the contents of the document are updated as the replication status changes.

In particular, once replication starts, three new fields are added automatically to the replication document. The fields all have the prefix: _replication_

Field Detail
_replication_id This is the internal ID assigned to the replication. It is the same ID that appears in the output from /_active_tasks/.
_replication_state The current state of the replication. The possible states are:
triggered
The replication has started and is in progress.
completed
The replication completed successfully.
error
An error occurred during replication.
_replication_state_time An RFC 3339 compliant timestamp that reports when the current replication state defined in _replication_state was set.

Example replication document once replication has completed:

{
  "_id": "my_rep",
  "source":  "https://username:password@myserver.com:5984/fromthis",
  "target":  "https://username:password@username.cloudant.com/tothat",
  "create_target":  true,
  "_replication_id":  "c0ebe9256695ff083347cbf95f93e280",
  "_replication_state":  "completed",
  "_replication_state_time":  "2011-06-07T16:56:21+01:00"
}

When the replication finishes, it updates the _replication_state field with the value completed, and the _replication_state_time field with the time that the completion status was recorded.

A continuous replication can never have a completed state.

Authentication

Example of specifying username and password values for accessing source and target databases during replication:

{
  "source": "https://username:password@example.com/db", 
  "target": "https://username:password@username.cloudant.com/db"
}

In any production application, security of the source and target databases is essential. In order for replication to proceed, authentication is necessary to access the databases. In addition, checkpoints for replication are enabled by default, which means that replicating the source database requires write access.

To enable authentication during replication, include a username and password in the database URL. The replication process uses the supplied values for HTTP Basic Authentication.

Filtered Replication

Simple example of a filter function:

function(doc, req) {
  return !!(doc.type && doc.type == "foo");
}

Sometimes you do not want to transfer all documents from source to target. To choose which documents to transfer, include one or more filter functions in a design document on the source. You can then tell the replicator to use these filter functions.

A filter function takes two arguments:

A filter function returns a true or false value. If the result is true, the document is replicated.

Simple example of storing a filter function in a design document:

{
  "_id": "_design/myddoc",
  "filters": {
    "myfilter": "function goes here"
  }
}

Filters are stored under the top-level filters key of the design document.

Example JSON for invoking a filtered replication:

{
  "source": "http://username:password@example.org/example-database",
  "target": "http://username:password@username.cloudant.com/example-database",
  "filter": "myddoc/myfilter"
}

Filters are invoked by using a JSON statement that identifies:

Example JSON for invoking a filtered replication with supplied parameters:

{
  "source": "http://username:password@example.org/example-database",
  "target": "http://username:password@username.cloudant.com/example-database",
  "filter": "myddoc/myfilter",
  "query_params": {
    "key": "value"
  }
}

Arguments can be supplied to the filter function by including key:value pairs in the query_params field of the invocation.

Named Document Replication

Example replication of specific documents:

{
  "source": "http://username:password@example.org/example-database",
  "target": "http://username:password@127.0.0.1:5984/example-database",
  "doc_ids": ["foo", "bar", "baz"]
}

Sometimes you only want to replicate some documents. For this simple case, you do not need to write a filter function. To replicate specific documents, add the list of keys as an array in the doc_ids field.

Replicating through a proxy

Example showing replication through a proxy:

{
  "source": "http://username:password@username.cloudant.com/example-database",
  "target": "http://username:password@example.org/example-database",
  "proxy": "http://my-proxy.com:8888"
}

If you want replication to pass through an HTTP proxy, provide the proxy details in the proxy field of the replication data.

The user_ctx property and delegations

Example delegated replication document:

{
  "_id": "my_rep",
  "source":  "https://username:password@myserver.com:5984/foo",
  "target":  "https://username:password@username.cloudant.com/bar",
  "continuous":  true,
  "user_ctx": {
    "name": "joe",
    "roles": ["erlanger", "researcher"]
  }
}

Replication documents can have a custom user_ctx property. This property defines the user context under which a replication runs. For the old way of triggering replications (POSTing to /_replicate/), this property was not needed (it didn’t exist in fact) -this is because at the moment of triggering the replication it has information about the authenticated user. With the replicator database, since it’s a regular database, the information about the authenticated user is only present at the moment the replication document is written to the database - the replicator database implementation is like a _changes feed consumer (with ?include_docs=true) that reacts to what was written to the replicator database - in fact this feature could be implemented with an external script/program. This implementation detail implies that for non admin users, a user_ctx property, containing the user’s name and a subset of his/her roles, must be defined in the replication document. This is ensured by the document update validation function present in the default design document of the replicator database. This validation function also ensure that a non admin user can set a user name property in the user_ctx property that doesn’t match his/her own name (same principle applies for the roles).

For admins, the user_ctx property is optional, and if it’s missing it defaults to a user context with name null and an empty list of roles - this means design documents will not be written to local targets. If writing design documents to local targets is desired, then a user context with the roles _admin must be set explicitly.

Also, for admins the user_ctx property can be used to trigger a replication on behalf of another user. This is the user context that will be passed to local target database document validation functions.

As stated before, for admins the user_ctx property is optional, while for regular (non admin) users it’s mandatory. When the roles property of user_ctx is missing, it defaults to the empty list [ ].

Example of including performance options in a replication document:

{
  "source": "https://username:password@example.com/example-database",
  "target": "https://username:password@example.org/example-database",
  "connection_timeout": 60000,
  "retries_per_request": 20,
  "http_connections": 30
}

These options can be set for a replication by including them in the replication document.

Active tasks

The /_active_tasks endpoint provides a list of the tasks running on the server. For more examples on using this endpoint, see the Managing tasks guide.

Retrieving a list of active tasks

Example request to retrieve list of active tasks:

GET /_active_tasks HTTP/1.1
curl https://$USERNAME.cloudant.com/_active_tasks \
     -u $USERNAME
var nano = require('nano');
var account = nano('https://$USERNAME:$PASSWORD@$USERNAME.cloudant.com');

account.request({
  path: '_active_tasks'
}, function (err, body) {
  if (!err) {
    console.log(body);
  }
});

Example JSON response array, containing details of currently running tasks:

[
  {
    "user": null,
    "updated_on": 1363274088,
    "type": "replication",
    "target": "https://repl:*****@tsm.cloudant.com/user-3dglstqg8aq0uunzimv4uiimy/",
    "docs_read": 0,
    "doc_write_failures": 0,
    "doc_id": "tsm-admin__to__user-3dglstqg8aq0uunzimv4uiimy",
    "continuous": true,
    "checkpointed_source_seq": "403-g1AAAADfeJzLYWBgYMlgTmGQS0lKzi9KdUhJMjTRyyrNSS3QS87JL01JzCvRy0styQGqY0pkSLL___9_VmIymg5TXDqSHIBkUj1YUxyaJkNcmvJYgCRDA5AC6tuflZhGrPsgGg9ANAJtzMkCAPFSStc",
    "changes_pending": 134,
    "pid": "<0.1781.4101>",
    "node": "dbcore@db11.julep.cloudant.net",
    "docs_written": 0,
    "missing_revisions_found": 0,
    "replication_id": "d0cdbfee50a80fd43e83a9f62ea650ad+continuous",
    "revisions_checked": 0,
    "source": "https://repl:*****@tsm.cloudant.com/tsm-admin/",
    "source_seq": "537-g1AAAADfeJzLYWBgYMlgTmGQS0lKzi9KdUhJMjTUyyrNSS3QS87JL01JzCvRy0styQGqY0pkSLL___9_VmI9mg4jXDqSHIBkUj1WTTityWMBkgwNQAqob39WYhextkE0HoBoBNo4MQsAFuVLVQ",
    "started_on": 1363274083
  },

  {
    "user": "acceptly",
    "updated_on": 1363273779,
    "type": "indexer",
    "node": "dbcore@db11.julep.cloudant.net",
    "pid": "<0.20723.4070>",
    "changes_done": 189,
    "database": "shards/00000000-3fffffff/acceptly/acceptly_my_chances_logs_live.1321035717",
    "design_document": "_design/MyChancesLogCohortReport",
    "started_on": 1363273094,
    "total_changes": 26389
  },

  {
    "user": "username",
    "updated_on": 1371118433,
    "type": "search_indexer",
    "total_changes": 5466,
    "node": "dbcore@db7.meritage.cloudant.net",
    "pid": "<0.29569.7037>",
    "changes_done": 4611,
    "database": "shards/40000000-7fffffff/username/database_name",
    "design_document": "_design/lucene",
    "index": "search1",
    "started_on": 1371118426
  },

  {
    "view": 1,
    "user": "acceptly",
    "updated_on": 1363273504,
    "type": "view_compaction",
    "total_changes": 26095,
    "node": "dbcore@db11.julep.cloudant.net",
    "pid": "<0.21218.4070>",
    "changes_done": 20000,
    "database": "shards/80000000-bfffffff/acceptly/acceptly_my_chances_logs_live.1321035717",
    "design_document": "_design/MyChancesLogCohortReport",
    "phase": "view",
    "started_on": 1363273094
  },

  {
    "updated_on": 1363274040,
    "node": "dbcore@db11.julep.cloudant.net",
    "pid": "<0.29256.4053>",
    "changes_done": 272195,
    "database": "shards/00000000-3fffffff/heroku/app3245179/id_f21a08b7005e_logs.1346083461",
    "started_on": 1363272496,
    "total_changes": 272195,
    "type": "database_compaction"
  }
]

You can obtain a list of active tasks by using the /_active_tasks URL. The result is a JSON array of the currently running tasks, with each task being described with a single object.

The returned structure includes the following fields for each task:

In the type field, possible values include:

The meaning of other fields in the JSON response depends on the type of the task.

Specific response fields for compaction tasks

In the phase field, the value indicates the stage that compaction has reached:

  1. ids: Document compaction is in progress.
  2. views: View compaction is in progress.

Specific response fields for replication tasks

Specific response fields for indexing tasks

Advanced

These endpoints provide information about the state of the cluster, details about revision history, and other miscellaneous tasks.

GET /

Example request to get server meta information:

GET / HTTP/1.1
curl https://$USERNAME.cloudant.com/ \
     -u $USERNAME
var nano = require('nano');
var account = nano('https://$USERNAME:$PASSWORD@$USERNAME.cloudant.com');

account.request({
  path: '/'
}, function (err, body) {
  if (!err) {
    console.log(body);
  }
});

Example JSON response:

{
  "couchdb": "Welcome",
  "version": "1.0.2",
  "cloudant_build":"1138"
}

Accessing the database rather than a document within the database returns meta information about the server. The response is a JSON structure containing information about the server, including a welcome message and the version of the server. The version field contains the CouchDB version the server is compatible with. The cloudant_build field contains the build number of Cloudant’s CouchDb implementation.

GET /_db_updates

Example request to get a list of changes to the database:

GET /_db_updates HTTP/1.1
curl https://$USERNAME.cloudant.com/_db_updates \
     -u $USERNAME
var nano = require('nano');
var account = nano('https://$USERNAME:$PASSWORD@$USERNAME.cloudant.com');

account.request({
  path: '_db_updates'
}, function (err, body) {
  if (!err) {
    console.log(body);
  }
});

Example response:

{
  "results": [{
    "dbname": "$DATABASE_NAME",
    "type": "created",
    "account": "$USERNAME",
    "seq": "673-g1AAAAJAeJyN0Et..."
  }],
  "last_seq": "673-g1AAAAJAeJyN0Et..."
}

Obtains a list of changes to databases, like a global changes feed. Changes can be either updates to the database, creation, or deletion of a database. Like the changes feed, the feed is not guaranteed to return changes in the correct order and might contain changes more than once. Polling modes for this method works just like polling modes for the changes feed.

Argument Description Optional Type Default Supported Values
feed Type of feed yes string normal continuous: Continuous (non-polling) mode, longpoll: Long polling mode, normal: default polling mode
heartbeat Time in milliseconds after which an empty line is sent during longpoll or continuous if there have been no changes yes numeric 60000
limit Maximum number of results to return yes numeric none
since Start the results from changes immediately after the specified sequence number. If since is 0 (the default), the request will return all changes since the feature was activated. yes string 0
timeout Number of milliseconds to wait for data in a longpoll or continuous feed before terminating the response. If both heartbeat and timeout are suppled, heartbeat supersedes timeout. yes numeric
descending Whether results should be returned in descending order, i.e. the latest event first. By default, the oldest event is returned first. yes boolean false

GET /$DB/_shards

Example request

GET /$DATABASE/_shards HTTP/1.1
curl https://$USERNAME.cloudant.com/$DATABASE/_shards \
     -u $USERNAME
var nano = require('nano');
var account = nano('https://$USERNAME:$PASSWORD@$USERNAME.cloudant.com');

account.request({
  database: $DATABASE,
  path: '_shards'
}, function (err, body) {
  if (!err) {
    console.log(body);
  }
});

Example response:

{
  "shards": {
    "e0000000-ffffffff": [
      "dbcore@db1.testy004.cloudant.net",
      "dbcore@db2.testy004.cloudant.net",
      "dbcore@db3.testy004.cloudant.net"
    ],
    "c0000000-dfffffff": [
      "dbcore@db1.testy004.cloudant.net",
      "dbcore@db2.testy004.cloudant.net",
      "dbcore@db3.testy004.cloudant.net"
    ],
    "a0000000-bfffffff": [
      "dbcore@db1.testy004.cloudant.net",
      "dbcore@db2.testy004.cloudant.net",
      "dbcore@db3.testy004.cloudant.net"
    ],
    "80000000-9fffffff": [
      "dbcore@db1.testy004.cloudant.net",
      "dbcore@db2.testy004.cloudant.net",
      "dbcore@db3.testy004.cloudant.net"
    ],
    "60000000-7fffffff": [
      "dbcore@db1.testy004.cloudant.net",
      "dbcore@db2.testy004.cloudant.net",
      "dbcore@db3.testy004.cloudant.net"
    ],
    "40000000-5fffffff": [
      "dbcore@db1.testy004.cloudant.net",
      "dbcore@db2.testy004.cloudant.net",
      "dbcore@db3.testy004.cloudant.net"
    ],
    "20000000-3fffffff": [
      "dbcore@db1.testy004.cloudant.net",
      "dbcore@db2.testy004.cloudant.net",
      "dbcore@db3.testy004.cloudant.net"
    ],
    "00000000-1fffffff": [
      "dbcore@db1.testy004.cloudant.net",
      "dbcore@db2.testy004.cloudant.net",
      "dbcore@db3.testy004.cloudant.net"
    ]
  }
}

Returns informations about the shards in the cluster, specifically what nodes contain what hash ranges.

The response’s shards field contains an object whose keys are the hash value range constituting each shard, while each value is the array of nodes containing that a copy of that shard.

GET /$DB/_missing_revs

Example request

GET /$DATABASE/_missing_revs
Content-Type: application/json
curl https://$USERNAME.cloudant.com/$DATABASE/_missing_revs \
     -X POST \
     -u "$USERNAME:$PASSWORD" \
     -H "Content-Type: application/json" \
     -d @request-body.json
# where the file request-body.json contains the following:
var nano = require('nano');
var account = nano('https://$USERNAME:$PASSWORD@$USERNAME.cloudant.com');

account.request({
  database: $DATABASE,
  path: '_missing_revs',
  method: 'POST',
  body: '$JSON'
}, function (err, body) {
  if (!err) {
    console.log(body);
  }
});
{
  "$DOCUMENT_ID": [
    "$REV_1",
    "$REV_2"
  ]
}

Example response:

{
  "missed_revs":{
    "$DOCUMENT_ID": [
      "$REV_1"
    ]
  }
}

Given a list of document revisions, returns the document revisions that do not exist in the database.

POST /$DB/_revs_diff

Example request

POST /$DATABASE/_revs_diff HTTP/1.1
curl https://$USERNAME.cloudant.com/$DATABASE/_revs_diff \
     -X POST \
     -u $USERNAME \
     -d "$JSON"
var nano = require('nano');
var account = nano('https://$USERNAME:$PASSWORD@$USERNAME.cloudant.com');

account.request({
  database: $DATABASE,
  path: '_revs_diff',
  method: 'POST',
  body: '$JSON'
}, function (err, body) {
  if (!err) {
    console.log(body);
  }
});

Example request:

{
  "190f721ca3411be7aa9477db5f948bbb": [
    "3-bb72a7682290f94a985f7afac8b27137",
    "4-10265e5a26d807a3cfa459cf1a82ef2e",
    "5-067a00dff5e02add41819138abb3284d"
  ]
}

Example response:

{
  "190f721ca3411be7aa9477db5f948bbb": {
    "missing": [
      "3-bb72a7682290f94a985f7afac8b27137",
      "5-067a00dff5e02add41819138abb3284d"
    ],
    "possible_ancestors": [
      "4-10265e5a26d807a3cfa459cf1a82ef2e"
    ]
  }
}

Given a set of document/revision IDs, returns the subset of those that do not correspond to revisions stored in the database.

GET /$DB/_revs_limit

Example request

var nano = require('nano');
var account = nano('https://$USERNAME:$PASSWORD@$USERNAME.cloudant.com');

account.request({
  path: '_revs_limit'
}, function (err, body) {
  if (!err) {
    console.log(body);
  }
});
GET /$DATABASE/_revs_limit HTTP/1.1
curl https://$USERNAME.cloudant.com/$DATABASE/_revs_limit \
     -X GET \
     -u "$USERNAME:$PASSWORD"

Example response:

1000

Gets the number of past revisions of a document that Cloudant stores information on.

PUT /$DB/_revs_limit

Example request

PUT /$DB/_revs_limit HTTP/1.1
curl https://$USERNAME.cloudant.com/_revs_limit \
     -u $USERNAME \
     -X PUT \
     -d 1000
var nano = require('nano');
var account = nano('https://$USERNAME:$PASSWORD@$USERNAME.cloudant.com');

account.request({
  path: '_revs_limit',
  body: '1000',
  method: 'PUT'
}, function (err, body) {
  if (!err) {
    console.log(body);
  }
});
1000

Example response:

{
  "ok": true
}

Sets the maximum number of past revisions that Cloudant stores information on.

GET /_membership

Example request to list nodes in the cluster:

GET /_membership HTTP/1.1
curl https://$USERNAME.cloudant.com/_membership \
     -u $USERNAME
var nano = require('nano');
var account = nano('https://$USERNAME:$PASSWORD@$USERNAME.cloudant.com');

account.request({
  path: '_membership'
}, function (err, body) {
  if (!err) {
    console.log(body);
  }
});

Example response:

{
  "cluster_nodes": [
    "dbcore@db1.testy004.cloudant.net",
    "dbcore@db2.testy004.cloudant.net",
    "dbcore@db3.testy004.cloudant.net"
  ],
  "all_nodes": [
    "dbcore@db1.testy004.cloudant.net",
    "dbcore@db2.testy004.cloudant.net",
    "dbcore@db3.testy004.cloudant.net"
  ]
}

Returns the names of nodes in the cluster. Currently active clusters are indicated in the cluster_nodes field, while all_nodes lists all nodes active or not.

Response structure

GET /_uuids

Example request for a single UUID:

GET /_uuids HTTP/1.1
curl https://$USERNAME.cloudant.com/_uuids \
     -u $USERNAME
var nano = require('nano');
var account = nano('https://$USERNAME:$PASSWORD@$USERNAME.cloudant.com');

account.request({
  path: '_uuids'
}, function (err, body) {
  if (!err) {
    console.log(body);
  }
});

Example response to a request for a single UUID:

{
   "uuids" : [
      "7e4b5a14b22ec1cf8e58b9cdd0000da3"
   ]
}

Example request for five UUIDs:

GET /_uuids?count=5 HTTP/1.1
curl https://$USERNAME.cloudant.com/_uuids?count=5 \
     -u $USERNAME
var nano = require('nano');
var account = nano('https://$USERNAME:$PASSWORD@$USERNAME.cloudant.com');

account.request({
  path: '_uuids?count=5'
}, function (err, body) {
  if (!err) {
    console.log(body);
  }
});

Example response to a request for five UUIDs:

{
   "uuids" : [
      "c9df0cdf4442f993fc5570225b405a80",
      "c9df0cdf4442f993fc5570225b405bd2",
      "c9df0cdf4442f993fc5570225b405e42",
      "c9df0cdf4442f993fc5570225b4061a0",
      "c9df0cdf4442f993fc5570225b406a20"
   ]
}

This command requests one or more Universally Unique Identifiers (UUIDs). The response is a JSON object providing a list of UUIDs.

Argument Description Optional Type
count Number of UUIDs to return yes Positive integer, greater than 0 and less than or equal to 1,000.

Next: Guides

Language: