9.3.4. /db/_changes — Apache CouchDB 1.7 Documentation

# 9.3.4. `/db/_changes`

`GET` `/{db}/_changes`

  Returns a sorted list of changes made to documents in the database, in time order of application, can be obtained from the database’s `_changes` resource. Only the most recent change for a given document is guaranteed to be provided, for example if a document has had fields added, and then deleted, an API client checking for changes will not necessarily receive the intermediate state of added documents.

  This can be used to listen for update and modifications to the database for post processing or synchronization, and for practical purposes, a continuously connected `_changes` feed is a reasonable approach for generating a real-time log for most applications.

  Parameters: | db – Database name
  Request Headers:
  | Accept – application/json text/event-stream text/plain Last-Event-ID – ID of the last events received by the server on a previous connection. Overrides since query parameter.
  Query Parameters:
  | doc_ids (array) – List of document IDs to filter the changes feed as valid JSON array. Used with _doc_ids filter. Since length of URL is limited, it is better to use `POST /{db}/_changes` instead. conflicts (boolean) – Includes conflicts information in response. Ignored if include_docs isn’t `true`. Default is `false`. descending (boolean) – Return the change results in descending sequence order (most recent change first). Default is `false`. feed (string) – see Changes Feeds. Default is `normal`. filter (string) – Reference to a filter function from a design document that will filter whole stream emitting only filtered events. See the section Change Notifications in the book CouchDB The Definitive Guide for more information. heartbeat (number) – Period in milliseconds after which an empty line is sent in the results. Only applicable for longpoll or continuous feeds. Overrides any timeout to keep the feed alive indefinitely. Default is `60000`. May be `true` to use default value. include_docs (boolean) – Include the associated document with each result. If there are conflicts, only the winning revision is returned. Default is `false`. attachments (boolean) – Include the Base64-encoded content of attachments in the documents that are included if include_docs is `true`. Ignored if include_docs isn’t `true`. Default is `false`. att_encoding_info (boolean) – Include encoding information in attachment stubs if include_docs is `true` and the particular attachment is compressed. Ignored if include_docs isn’t `true`. Default is `false`. last-event-id (number) – Alias of Last-Event-ID header. limit (number) – Limit number of result rows to the specified value (note that using `0` here has the same effect as `1`). since – Start the results from the change immediately after the given sequence number. Can be integer number or `now` value. Default is `0`. style (string) – Specifies how many revisions are returned in the changes array. The default, `main_only`, will only return the current “winning” revision; `all_docs` will return all leaf revisions (including conflicts and deleted former conflicts). timeout (number) – Maximum period in milliseconds to wait for a change before the response is sent, even if there are no results. Only applicable for longpoll or continuous feeds. Default value is specified by `httpd/changes_timeout` configuration option. Note that `60000` value is also the default maximum timeout to prevent undetected dead connections. view (string) – Allows to use view functions as filters. Documents counted as “passed” for view filter in case if map function emits at least one record for them. See _view for more info.
  Response Headers:
  | Cache-Control – `no-cache` if changes feed is eventsource Content-Type – application/json text/event-stream text/plain; charset=utf-8 ETag – Response hash is changes feed is normal Transfer-Encoding – `chunked`
  Response JSON Object:
  | last_seq (number) – Last change sequence number results (array) – Changes made to a database
  Status Codes: | 200 OK – Request completed successfully 400 Bad Request – Bad request

  The `result` field of database changes

  JSON Object: | changes (array) – List of document`s leafs with single field `rev` id (string) – Document ID seq (number) – Update sequence number

  Request:

      GET /db/_changes?style=all_docs HTTP/1.1
      Accept: application/json
      Host: localhost:5984

  Response:

      HTTP/1.1 200 OK
      Cache-Control: must-revalidate
      Content-Type: application/json
      Date: Mon, 12 Aug 2013 00:54:58 GMT
      ETag: "6ASLEKEMSRABT0O5XY9UPO9Z"
      Server: CouchDB (Erlang/OTP)
      Transfer-Encoding: chunked

      {
          "last_seq": 11,
          "results": [
              {
                  "changes": [
                      {
                          "rev": "2-7051cbe5c8faecd085a3fa619e6e6337"
                      }
                  ],
                  "id": "6478c2ae800dfc387396d14e1fc39626",
                  "seq": 6
              },
              {
                  "changes": [
                      {
                          "rev": "3-7379b9e515b161226c6559d90c4dc49f"
                      }
                  ],
                  "deleted": true,
                  "id": "5bbc9ca465f1b0fcd62362168a7c8831",
                  "seq": 9
              },
              {
                  "changes": [
                      {
                          "rev": "6-460637e73a6288cb24d532bf91f32969"
                      },
                      {
                          "rev": "5-eeaa298781f60b7bcae0c91bdedd1b87"
                      }
                  ],
                  "id": "729eb57437745e506b333068fff665ae",
                  "seq": 11
              }
          ]
      }

Changed in version 0.11.0: added `include_docs` parameter

Changed in version 1.2.0: added `view` parameter and special value _view for `filter` one

Changed in version 1.3.0: `since` parameter could take now value to start listen changes since current seq number.

Changed in version 1.3.0: `eventsource` feed type added.

Changed in version 1.4.0: Support `Last-Event-ID` header.

Changed in version 1.6.0: added `attachments` and `att_encoding_info` parameters

Warning

Using the `attachments` parameter to include attachments in the changes feed is not recommended for large attachment sizes. Also note that the Base64-encoding that is used leads to a 33% overhead (i.e. one third) in transfer size for attachments.

`POST` `/{db}/_changes`

  Requests the database changes feed in the same way as `GET /{db}/_changes` does, but is widely used with `?filter=_doc_ids` query parameter and allows one to pass a larger list of document IDs to filter.

  Request:

      POST /recipes/_changes?filter=_doc_ids HTTP/1.1
      Accept: application/json
      Content-Length: 40
      Content-Type: application/json
      Host: localhost:5984

      {
          "doc_ids": [
              "SpaghettiWithMeatballs"
          ]
      }

  Response:

      HTTP/1.1 200 OK
      Cache-Control: must-revalidate
      Content-Type: application/json
      Date: Sat, 28 Sep 2013 07:23:09 GMT
      ETag: "ARIHFWL3I7PIS0SPVTFU6TLR2"
      Server: CouchDB (Erlang OTP)
      Transfer-Encoding: chunked

      {
          "last_seq": 38,
          "results": [
              {
                  "changes": [
                      {
                          "rev": "13-bcb9d6388b60fd1e960d9ec4e8e3f29e"
                      }
                  ],
                  "id": "SpaghettiWithMeatballs",
                  "seq": 38
              }
          ]
      }

## Changes Feeds

### Polling

By default all changes are immediately returned within the JSON body:

    GET /somedatabase/_changes HTTP/1.1

    {"results":[
    {"seq":1,"id":"fresh","changes":[{"rev":"1-967a00dff5e02add41819138abb3284d"}]},
    {"seq":3,"id":"updated","changes":[{"rev":"2-7051cbe5c8faecd085a3fa619e6e6337"}]},
    {"seq":5,"id":"deleted","changes":[{"rev":"2-eec205a9d413992850a6e32678485900"}],"deleted":true}
    ],
    "last_seq":5}

`results` is the list of changes in sequential order. New and changed documents only differ in the value of the rev; deleted documents include the `"deleted": true` attribute. (In the `style=all_docs mode`, deleted applies only to the current/winning revision. The other revisions listed might be deleted even if there is no deleted property; you have to `GET` them individually to make sure.)

`last_seq` is the sequence number of the last update returned. (Currently it will always be the same as the seq of the last item in results.)

Sending a `since` param in the query string skips all changes up to and including the given sequence number:

    GET /somedatabase/_changes?since=3 HTTP/1.1

The return structure for `normal` and `longpoll` modes is a JSON array of changes objects, and the last update sequence number.

In the return format for `continuous` mode, the server sends a `CRLF` (carriage-return, linefeed) delimited line for each change. Each line contains the JSON object described above.

You can also request the full contents of each document change (instead of just the change notification) by using the `include_docs` parameter.

    {
        "last_seq": 5
        "results": [
            {
                "changes": [
                    {
                        "rev": "2-eec205a9d413992850a6e32678485900"
                    }
                ],
                "deleted": true,
                "id": "deleted",
                "seq": 5,
            }
        ]
    }

### Long Polling

The longpoll feed, probably most applicable for a browser, is a more efficient form of polling that waits for a change to occur before the response is sent. longpoll avoids the need to frequently poll CouchDB to discover nothing has changed!

The request to the server will remain open until a change is made on the database and is subsequently transferred, and then the connection will close. This is low load for both server and client.

The response is basically the same JSON as is sent for the normal feed.

Because the wait for a change can be significant you can set a timeout before the connection is automatically closed (the `timeout` argument). You can also set a heartbeat interval (using the `heartbeat` query argument), which sends a newline to keep the connection active.

### Continuous

Continually polling the CouchDB server is not ideal - setting up new HTTP connections just to tell the client that nothing happened puts unnecessary strain on CouchDB.

A continuous feed stays open and connected to the database until explicitly closed and changes are sent to the client as they happen, i.e. in near real-time.

As with the longpoll feed type you can set both the timeout and heartbeat intervals to ensure that the connection is kept open for new changes and updates.

The continuous feed’s response is a little different than the other feed types to simplify the job of the client - each line of the response is either empty or a JSON object representing a single change, as found in the normal feed’s results.

    GET /somedatabase/_changes?feed=continuous HTTP/1.1

    {"seq":1,"id":"fresh","changes":[{"rev":"1-967a00dff5e02add41819138abb3284d"}]}
    {"seq":3,"id":"updated","changes":[{"rev":"2-7051cbe5c8faecd085a3fa619e6e6337"}]}
    {"seq":5,"id":"deleted","changes":[{"rev":"2-eec205a9d413992850a6e32678485900"}],"deleted":true}
    ... tum tee tum ...
    {"seq":6,"id":"updated","changes":[{"rev":"3-825cb35de44c433bfb2df415563a19de"}]}

Obviously, ... tum tee tum ... does not appear in the actual response, but represents a long pause before the change with seq 6 occurred.

### Event Source

The eventsource feed provides push notifications that can be consumed in the form of DOM events in the browser. Refer to the W3C eventsource specification for further details. CouchDB also honours the `Last-Event-ID` parameter.

    GET /somedatabase/_changes?feed=eventsource HTTP/1.1

    // define the event handling function
    if (window.EventSource) {

      var source = new EventSource("/somedatabase/_changes?feed=eventsource");
      source.onerror = function(e) {
        alert('EventSource failed.');
      };

      var results = [];
      var sourceListener = function(e) {
        var data = JSON.parse(e.data);
        results.push(data);
      };

      // start listening for events
      source.addEventListener('message', sourceListener, false);

      // stop listening for events
      source.removeEventListener('message', sourceListener, false);

    }

Note

EventSource connections are subject to cross-origin resource sharing restrictions. You might need to configure CORS support to get the EventSource to work in your application.

## Filtering

You can filter the contents of the changes feed in a number of ways. The most basic way is to specify one or more document IDs to the query. This causes the returned structure value to only contain changes for the specified IDs. Note that the value of this query argument should be a JSON formatted array.

You can also filter the `_changes` feed by defining a filter function within a design document. The specification for the filter is the same as for replication filters. You specify the name of the filter function to the `filter` parameter, specifying the design document name and filter name. For example:

    GET /db/_changes?filter=design_doc/filtername

Additionally, there are couple of builtin filters are available and described below.

### _doc_ids

This filter accepts only changes for documents which ID in specified in `doc_ids` query parameter or payload’s object array. See `POST /{db}/_changes` for an example.

### _design

The `_design` filter accepts only changes for any design document within the requested database.

Request:

    GET /recipes/_changes?filter=_design HTTP/1.1
    Accept: application/json
    Host: localhost:5984

Response:

    HTTP/1.1 200 OK
    Cache-Control: must-revalidate
    Content-Type: application/json
    Date: Sat, 28 Sep 2013 07:28:28 GMT
    ETag: "ARIHFWL3I7PIS0SPVTFU6TLR2"
    Server: CouchDB (Erlang OTP)
    Transfer-Encoding: chunked

    {
        "last_seq": 38,
        "results": [
            {
                "changes": [
                    {
                        "rev": "10-304cae84fd862832ea9814f02920d4b2"
                    }
                ],
                "id": "_design/ingredients",
                "seq": 29
            },
            {
                "changes": [
                    {
                        "rev": "123-6f7c1b7c97a9e4f0d22bdf130e8fd817"
                    }
                ],
                "deleted": true,
                "id": "_design/cookbook",
                "seq": 35
            },
            {
                "changes": [
                    {
                        "rev": "6-5b8a52c22580e922e792047cff3618f3"
                    }
                ],
                "deleted": true,
                "id": "_design/meta",
                "seq": 36
            }
        ]
    }

### _view

New in version 1.2.

The special filter `_view` allows to use existing map function as the filter. If the map function emits anything for the processed document it counts as accepted and the changes event emits to the feed. For most use-practice cases filter functions are very similar to map ones, so this feature helps to reduce amount of duplicated code.

Warning

While map functions doesn’t process the design documents, using `_view` filter forces them to do this. You need to be sure, that they are ready to handle documents with alien structure without panic crush.

Note

Using `_view` filter doesn’t queries the view index files, so you cannot use common view query parameters to additionally filter the changes feed by index key. Also, CouchDB doesn’t returns the result instantly as it does for views - it really uses the specified map function as filter.

Moreover, you cannot make such filters dynamic e.g. process the request query parameters or handle the User Context Object - the map function is only operates with the document.

Request:

    GET /recipes/_changes?filter=_view&view=ingredients/by_recipe HTTP/1.1
    Accept: application/json
    Host: localhost:5984

Response:

    HTTP/1.1 200 OK
    Cache-Control: must-revalidate
    Content-Type: application/json
    Date: Sat, 28 Sep 2013 07:36:40 GMT
    ETag: "ARIHFWL3I7PIS0SPVTFU6TLR2"
    Server: CouchDB (Erlang OTP)
    Transfer-Encoding: chunked

    {
        "last_seq": 38,
        "results": [
            {
                "changes": [
                    {
                        "rev": "13-bcb9d6388b60fd1e960d9ec4e8e3f29e"
                    }
                ],
                "id": "SpaghettiWithMeatballs",
                "seq": 38
            }
        ]
    }