{"id":7470,"date":"2015-09-28T21:11:24","date_gmt":"2015-09-28T18:11:24","guid":{"rendered":"http:\/\/www.webcodegeeks.com\/?p=7470"},"modified":"2018-01-05T16:53:10","modified_gmt":"2018-01-05T14:53:10","slug":"couchdb-basics-and-operations","status":"publish","type":"post","link":"https:\/\/www.webcodegeeks.com\/web-development\/couchdb-basics-and-operations\/","title":{"rendered":"CouchDB: Basics and Operations"},"content":{"rendered":"<p><em>This article is part of our Academy Course titled <a href=\"http:\/\/www.webcodegeeks.com\/2015\/09\/couchdb-database-for-the-web\/\">CouchDB \u2013 Database for the Web<\/a>.<\/p>\n<p>This is a hands-on course on CouchDB. You will learn how to install and configure CouchDB and how to perform common operations with it. Additionally, you will build an example application from scratch and then finish the course with more advanced topics like scaling, replication and load balancing. Check it out <a href=\"http:\/\/www.webcodegeeks.com\/2015\/09\/couchdb-database-for-the-web\/\">here<\/a>!<\/em><br \/>\n&nbsp;<br \/>\n&nbsp;<br \/>\n&nbsp;<br \/>\n&nbsp;<br \/>\n[ulp id=&#8217;tgm4cmEWcKUikZNn&#8217;]<\/p>\n<div class=\"toc\">\n<h4>Table Of Contents<\/h4>\n<dl>\n<dt><a href=\"#introduction\">1. Introduction<\/a><\/dt>\n<dt><a href=\"#Futon\">2. Futon<\/a><\/dt>\n<dd>\n<dl>\n<dt><a href=\"#Managing Databases and Documents\">2.1 Managing Databases and Documents<\/a><\/dt>\n<dt><a href=\"#Configuring Replication\">2.2 Configuring Replication<\/a><\/dt>\n<\/dl>\n<\/dd>\n<dt><a href=\"#create\/update\/delete databases and documents\">3. CRUD Operations<\/a><\/dt>\n<dd>\n<dl>\n<dt><a href=\"#Storing Documents\">3.1 Documents<\/a><\/dt>\n<\/dl>\n<\/dd>\n<dt><a href=\"#Common operations, HTTP operations, HTTP Headers, Errors, HTTP URL paths\">4. Common HTTP operations<\/a><\/dt>\n<dd>\n<dl>\n<dt><a href=\"#Databases\">4.1 Databases<\/a><\/dt>\n<dt><a href=\"#Documents\">4.2 Documents<\/a><\/dt>\n<dt><a href=\"#Attachments\">4.3 Attachments<\/a><\/dt>\n<dt><a href=\"#Replication\">4.4 Replication<\/a><\/dt>\n<\/dl>\n<\/dd>\n<dt><a href=\"#JSON\">5. JSON<\/a><\/dt>\n<dd>\n<dl>\n<dt><a href=\"#Data Types\">5.1 Data Types<\/a><\/dt>\n<dt><a href=\"#Numbers\">5.2 Numbers<\/a><\/dt>\n<dt><a href=\"#Strings\">5.3 Strings<\/a><\/dt>\n<dt><a href=\"#Booleans\">5.4 Booleans<\/a><\/dt>\n<\/dl>\n<\/dd>\n<dt><a href=\"#Document\">6. Documents<\/a><\/dt>\n<dd>\n<dl>\n<dt><a href=\"#Special Fields\">6.1 Special Fields<\/a><\/dt>\n<dt><a href=\"#Document IDs\">6.2 Document IDs<\/a><\/dt>\n<dt><a href=\"#Working With Documents Over HTTP\">6.3 Working With Documents Over HTTP<\/a><\/dt>\n<\/dl>\n<\/dd>\n<dt><a href=\"#Revisions\">7. Revisions<\/a><\/dt>\n<dd>\n<dl>\n<dt><a href=\"#Accessing Previous\">7.1 Accessing Previous Revisions<\/a><\/dt>\n<dt><a href=\"#HEAD\">7.2 HEAD<\/a><\/dt>\n<dt><a href=\"#PUT\">7.3 PUT<\/a><\/dt>\n<dt><a href=\"#POST\">7.4 POST<\/a><\/dt>\n<dt><a href=\"#DELETE\">7.5 DELETE<\/a><\/dt>\n<dt><a href=\"#COPY\">7.6 COPY<\/a><\/dt>\n<dt><a href=\"#All Documents\">7.7 All Documents<\/a><\/dt>\n<\/dl>\n<\/dd>\n<dt><a href=\"#http:\/\/guide.couchdb.org\/draft\/api.html#replication\">8. Replication<\/a><\/dt>\n<\/dl>\n<\/div>\n<h2><a name=\"introduction\"><\/a>1. Introduction<\/h2>\n<p>As we saw in our <a href=\"http:\/\/www.webcodegeeks.com\/2015\/09\/couchdb-installation-how-to-install-couchdb\/\">introductory lesson<\/a>, Apache CouchDB is an open source NoSQL database that uses JSON to store data, JavaScript as its query language and HTTP for an API. In CouchDB, each database is actually a collection of documents. Each document maintains its own data and a self-contained schema. An application may access multiple databases on different servers and Document metadata contain revision information in order to make merging possible in case the databases get disconnected.<\/p>\n<p>In CouchDB, all operations have a unique URI that gets exposed via HTTP. The REST APIs use the typical HTTP methods POST, GET, PUT and DELETE for the four basic CRUD (Create, Read, Update, Delete) operations on all resources. Finally, Futon is CouchDB&#8217;s web-based administration console. Let&#8217;s see more details for those components.<\/p>\n<h2><a name=\"Futon\"><\/a>2. Futon<\/h2>\n<p>Futon will can be accessed by a browser via the following address: <a href=\"http:\/\/localhost:5984\/_utils\/\">http:\/\/localhost:5984\/_utils\/<\/a><\/p>\n<p>The main overview page provides a list of the databases and provides the interface for querying the database and creating and updating documents.<\/p>\n<p>The main sections in Futon are:<\/p>\n<ol>\n<li><strong>Configuration:<\/strong> An interface into the configuration of Wer CouchDB installation. The interface allows us to edit the different configurable parameters.<\/li>\n<li><strong>Replicator:<\/strong> An interface to the replication system, enabling us to initiate replication between local and remote databases.<\/li>\n<li><strong>Status:<\/strong> Displays a list of the running background tasks on the server. Background tasks include view index building, compaction and replication. The Status page is an interface to the Active Tasks API call.<\/li>\n<li><strong>Verify Installation:<\/strong> The Verify Installation allows us to check whether all of the components of CouchDB installation are correctly installed.<\/li>\n<li><strong>Test Suite:<\/strong> The Test Suite section allows us to run the built-in test suite. This executes a number of test routines entirely within browser to test the API and functionality of CouchDB installation.<\/li>\n<\/ol>\n<h3><a name=\"Managing Databases and Documents\"><\/a>2.1 Managing Databases and Documents<\/h3>\n<p>We can manage databases and documents within Futon using the main Overview section of the Futon interface.<\/p>\n<p>To create a new database, click the Create Database Ellipsis button. We will be prompted for the database name, as shown in the figure below.<\/p>\n<figure id=\"attachment_3743\" aria-describedby=\"caption-attachment-3743\" style=\"width: 459px\" class=\"wp-caption aligncenter\"><a href=\"http:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2015\/09\/image004.png\"><img decoding=\"async\" class=\" wp-image-3743 \" alt=\"Create CouchDB Database\" src=\"http:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2015\/09\/image004.png\" width=\"459\" height=\"200\" \/><\/a><figcaption id=\"caption-attachment-3743\" class=\"wp-caption-text\">Create CouchDB Database<\/figcaption><\/figure>\n<p>Type the database name (i.e. &#8216;blog&#8217; here) in the textbox that we want to create.<\/p>\n<p>Once we have created the database (or selected an existing one), we will be shown a list of the current documents. If we create a new document, or select an existing document, we will be presented with the edit document display.<\/p>\n<p>Editing documents within Futon requires selecting the document and then editing (and setting) the fields for the document individually before saving the document back into the database.<\/p>\n<p>For example, the figure below shows the editor for a single document, a newly created document with a single ID, the document _id field (click on the image to show in full size).<\/p>\n<figure id=\"attachment_3745\" aria-describedby=\"caption-attachment-3745\" style=\"width: 300px\" class=\"wp-caption aligncenter\"><a href=\"http:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2015\/09\/image006.png\"><img decoding=\"async\" src=\"http:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2015\/09\/image006-300x55.png\" alt=\"New document\" width=\"300\" height=\"55\" class=\"size-medium wp-image-3745\" \/><\/a><figcaption id=\"caption-attachment-3745\" class=\"wp-caption-text\">New document<\/figcaption><\/figure>\n<p>To add a field to the document:<\/p>\n<ol>\n<li>Click Add Field.<\/li>\n<li>In the fieldname box, enter the name of the field. For example, \u201cblogger_name\u201d.<\/li>\n<li>Click the green tick next to the field name to confirm the field name change.<\/li>\n<p>&nbsp;<br \/>\n<figure id=\"attachment_3748\" aria-describedby=\"caption-attachment-3748\" style=\"width: 637px\" class=\"wp-caption aligncenter\"><a href=\"http:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2015\/09\/image008.png\"><img decoding=\"async\" src=\"http:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2015\/09\/image008.png\" alt=\"Changing a field name\" width=\"637\" height=\"162\" class=\"size-full wp-image-3748\" \/><\/a><figcaption id=\"caption-attachment-3748\" class=\"wp-caption-text\">Changing a field name<\/figcaption><\/figure><\/p>\n<li>Double-click the corresponding Value cell.<\/li>\n<li>Enter a company name, for example \u201cjohn\u201d.<\/li>\n<p>&nbsp;<br \/>\n<figure id=\"attachment_3746\" aria-describedby=\"caption-attachment-3746\" style=\"width: 595px\" class=\"wp-caption aligncenter\"><a href=\"http:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2015\/09\/image011.jpg\"><img decoding=\"async\" src=\"http:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2015\/09\/image011.jpg\" alt=\"Field name change\" width=\"595\" height=\"222\" class=\"size-full wp-image-3746\" \/><\/a><figcaption id=\"caption-attachment-3746\" class=\"wp-caption-text\">Field name changed<\/figcaption><\/figure><\/p>\n<li>Click the green tick next to the field value to confirm the field value.<\/li>\n<li>We must explicitly save the document by clicking the Save Document button at the top of the page. This will save the document, and then display the new document with the saved revision information (the _rev field). (Click on image to show in full size)<\/li>\n<p>&nbsp;<br \/>\n<figure id=\"attachment_3749\" aria-describedby=\"caption-attachment-3749\" style=\"width: 300px\" class=\"wp-caption aligncenter\"><a href=\"http:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2015\/09\/image012.png\"><img decoding=\"async\" src=\"http:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2015\/09\/image012-300x78.png\" alt=\"Document changes\" width=\"300\" height=\"78\" class=\"size-medium wp-image-3749\" \/><\/a><figcaption id=\"caption-attachment-3749\" class=\"wp-caption-text\">Document changes<\/figcaption><\/figure>\n<\/ol>\n<h3><a name=\"Configuring Replication\"><\/a>2.2 Configuring Replication<\/h3>\n<p>When we click the Replicator option within the Tools menu we are presented with the Replicator screen. This allows us to start replication between two databases by filling in or select the appropriate options within the form provided.<\/p>\n<p>For example, let&#8217;s say we have another database &#8216;test&#8217;. So the list of databases are the following:<\/p>\n<figure id=\"attachment_3751\" aria-describedby=\"caption-attachment-3751\" style=\"width: 556px\" class=\"wp-caption aligncenter\"><a href=\"http:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2015\/09\/image014.png\"><img decoding=\"async\" src=\"http:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2015\/09\/image014.png\" alt=\"Databases Overview\" width=\"556\" height=\"239\" class=\"size-full wp-image-3751\" \/><\/a><figcaption id=\"caption-attachment-3751\" class=\"wp-caption-text\">Databases Overview<\/figcaption><\/figure>\n<p>Now we are going to replicate database from &#8216;blog&#8217; to &#8216;test&#8217;.<\/p>\n<p>To do that, click on the &#8216;Replicator&#8217; on the right side panel.<\/p>\n<p>To start the replication process, either select the local database or enter a remote database name into the corresponding areas of the form. The replication occurs from the database on the left to the database on the right.<\/p>\n<p>If we are specifying a remote database name, we must specify the full URL of the remote database (including the host, port number and database name). If the remote instance requires authentication, we can specify the username and password as part of the URL, for example http:\/\/username:pass@remotehost:5984\/blog. (Click on image to show in full size)<\/p>\n<figure id=\"attachment_3752\" aria-describedby=\"caption-attachment-3752\" style=\"width: 1060px\" class=\"wp-caption aligncenter\"><a href=\"http:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2015\/09\/image016.png\"><img decoding=\"async\" src=\"http:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2015\/09\/image016.png\" alt=\"Remote CouchDB Replication\" width=\"1060\" height=\"138\" class=\"size-full wp-image-3752\" \/><\/a><figcaption id=\"caption-attachment-3752\" class=\"wp-caption-text\">Remote CouchDB Replication<\/figcaption><\/figure>\n<p>To enable continuous replication, click the Continuous checkbox. Click on the &#8216;Replicate&#8217; button.<\/p>\n<p>The replication process should start and will continue in the background. If the replication process takes a long time, we can monitor the status of the replication using the Status option under the Tools menu.<\/p>\n<p>Once the replication has been completed, the page will show the information using the CouchDB API.<\/p>\n<p>The result will be shown like in the following image (Click on image to show in full size):<\/p>\n<figure id=\"attachment_3753\" aria-describedby=\"caption-attachment-3753\" style=\"width: 1077px\" class=\"wp-caption aligncenter\"><a href=\"http:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2015\/09\/image018.png\"><img decoding=\"async\" src=\"http:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2015\/09\/image018.png\" alt=\"Replication Result\" width=\"1077\" height=\"116\" class=\"size-full wp-image-3753\" \/><\/a><figcaption id=\"caption-attachment-3753\" class=\"wp-caption-text\">Replication Result<\/figcaption><\/figure>\n<p>If we now open the &#8216;test&#8217; database, we will find an exact replica of the &#8216;blog&#8217; database:<\/p>\n<figure id=\"attachment_3754\" aria-describedby=\"caption-attachment-3754\" style=\"width: 1063px\" class=\"wp-caption aligncenter\"><a href=\"http:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2015\/09\/image020.png\"><img decoding=\"async\" src=\"http:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2015\/09\/image020.png\" alt=\"Successful Replication\" width=\"1063\" height=\"237\" class=\"size-full wp-image-3754\" \/><\/a><figcaption id=\"caption-attachment-3754\" class=\"wp-caption-text\">Successful Replication<\/figcaption><\/figure>\n<h2><a name=\"create\/update\/delete databases and documents\"><\/a>3. CRUD Operations<\/h2>\n<p>Next, we will have a quick look at CouchDB\u2019s bare-bones Application Programming Interface (API) by using the command-line utility &#8220;curl&#8221;. It gives us control over raw HTTP requests and we can see exactly what is going on the database.<\/p>\n<p>Make sure CouchDB is still running and then from the command line execute the following:<\/p>\n<pre class=\"brush:bash\">curl http:\/\/127.0.0.1:5984\/<\/pre>\n<p>This issues a GET request to the newly installed CouchDB instance. The reply should look something like:<\/p>\n<pre class=\"brush:bash\">{\"couchdb\":\"Welcome\",\"version\":\"1.0.1\"}<\/pre>\n<p>Next, we can get a list of the existing databases:<\/p>\n<pre class=\"brush:bash\">curl -X GET http:\/\/127.0.0.1:5984\/_all_dbs<\/pre>\n<p>Note that we added the &#8220;_all_dbs&#8221; string to the initial request.. The response should look like:<\/p>\n<pre class=\"brush:bash\">[\"_users\",\"blog\",\"test\"]<\/pre>\n<p>It is showing our 2 databases named blog and test which were created earlier via the Futon UI.<\/p>\n<p>Let\u2019s create another database, using the API this time:<\/p>\n<pre class=\"brush:bash\">curl -X PUT http:\/\/127.0.0.1:5984\/shopcart<\/pre>\n<p>Executing this, the CouchDB will reply with:<\/p>\n<pre class=\"brush:bash\">{\"ok\":true}<\/pre>\n<p>Retrieving the list of databases again shows some useful results:<\/p>\n<pre class=\"brush:bash\">curl -X GET http:\/\/127.0.0.1:5984\/_all_dbs<\/pre>\n<p>The output shows:<\/p>\n<pre class=\"brush:bash\">[\"_users\",\"blog\",\"shopcart\",\"test\"]<\/pre>\n<p>Let\u2019s create another database with the same database name:<\/p>\n<pre class=\"brush:bash\">curl -X PUT http:\/\/127.0.0.1:5984\/shopcart<\/pre>\n<p>CouchDB will reply with:<\/p>\n<pre class=\"brush:bash\">{\"error\":\"file_exists\",\"reason\":\"The database could not be created, the file already exists.\"}<\/pre>\n<p>We already have a database with that name, so CouchDB will respond with an error. Let\u2019s try again with a different database name:<\/p>\n<pre class=\"brush:bash\">curl -X PUT http:\/\/127.0.0.1:5984\/bookstore<\/pre>\n<p>CouchDB will reply with:<\/p>\n<pre class=\"brush:bash\">{\"ok\":true}<\/pre>\n<p>Retrieving the list of databases yet again shows some useful results:<\/p>\n<pre class=\"brush:bash\">curl -X GET http:\/\/127.0.0.1:5984\/_all_dbs<\/pre>\n<p>CouchDB will respond with:<\/p>\n<pre class=\"brush:bash\">[\"bookstore\",\"_users\",\"blog\",\"shopcart\",\"test\"]<\/pre>\n<p>To round things off, let\u2019s delete the second database:<\/p>\n<pre class=\"brush:bash\">curl -X DELETE http:\/\/127.0.0.1:5984\/bookstore<\/pre>\n<p>CouchDB will reply with:<\/p>\n<pre class=\"brush:bash\">{\"ok\":true}<\/pre>\n<p>The list of databases is now the same as it was before:<\/p>\n<pre class=\"brush:bash\">curl -X GET http:\/\/127.0.0.1:5984\/_all_dbs<\/pre>\n<p>CouchDB will respond with:<\/p>\n<pre class=\"brush:bash\">[\"_users\",\"blog\",\"shopcart\",\"test\"]<\/pre>\n<p>Everything is done using the standard HTTP methods, GET, PUT, POST, and DELETE with the appropriate URI.<\/p>\n<h3><a name=\"Storing Documents\"><\/a>3.1 <a href=\"http:\/\/guide.couchdb.org\/draft\/documents.html#documents\">Documents<\/a><em><\/em><\/h3>\n<p><em>Documents <\/em>are CouchDB\u2019s central data structure. To better understand and use CouchDB, we need to <em>think in terms of documents<\/em>. In this chapter we will walk though the lifecycle of designing and saving a document. We\u2019ll follow up by reading documents and aggregating and querying them with views.<\/p>\n<p>Documents are self-contained units of data. The data is usually made up of small native types such as integers and strings. Documents are the first level of abstraction over these native types. They provide some structure and logically group the primitive data. The height of a person might be encoded as an integer (<i>176<\/i>), but this integer is usually part of a larger structure that contains a label (<i>&#8220;height&#8221;: 176<\/i>) and related data (<i>{&#8220;name&#8221;:&#8221;Chris&#8221;, &#8220;height&#8221;: 176}<\/i>).<\/p>\n<p>How many data items can be put into the documents depends on the application and a bit on how we want to use views. Generally, a document corresponds to an object instance in the programming language.<\/p>\n<p>Documents differ subtly from garden-variety objects in that they usually have authors and CRUD operations (create, read, update, delete). Document-based software (like the word processors and spreadsheets) build their storage model around saving documents so that authors get back what they created.<\/p>\n<p>Validation functions are available so that we don\u2019t have to worry about bad data causing errors in our system. Often in document-based software, the client application edits and manipulates the data, saving it back.<\/p>\n<p>Let&#8217;s suppose a user can comment on the item (\u201clovely book\u201d); we have the option to store the comments as an array, on the item document. This makes it trivial to find the item\u2019s comments, but, as they say, \u201cit doesn\u2019t scale.\u201d A popular item could have tens of comments, or even hundreds or more.<\/p>\n<p>Instead of storing a list on the item document, in this case it may be acutally better to model comments into a collection of documents. There are patterns for accessing collections, which CouchDB makes easy. We likely want to show only 10 or 20 at a time and provide <em>previous <\/em>and <em>next <\/em>links. By handling comments as individual entities, we can group them with views. A group could be the entire collection or slices of 10 or 20, sorted by the item they apply to so that it\u2019s easy to grab the set we need.<\/p>\n<p>Everything that will be handled separately in the application should be broken up into documents. Items are single, and comments are single, but we don\u2019t need to break them into smaller pieces. Views provide a convenient way to group our documents in meaningful ways.<\/p>\n<h2><a name=\"Common operations, HTTP operations, HTTP Headers, Errors, HTTP URL paths\"><\/a>4. Common HTTP operations<\/h2>\n<p>We start out by revisiting the basic operations we ran in the last chapter, looking behind the scenes. We will also discover what Futon runs in the background in order to give us the nice features we saw earlier.<\/p>\n<p>While explaining the API bits and pieces, we sometimes need to take a larger detour to explain the reasoning for a particular request. This is a good opportunity for us to tell why CouchDB works the way it does.<\/p>\n<p>The API can be subdivided into the following sections. We\u2019ll explore them individually:<\/p>\n<ol>\n<li>Server<\/li>\n<li>Databases<\/li>\n<li>Documents<\/li>\n<li>Replication<\/li>\n<li>Server<\/li>\n<\/ol>\n<p>This one is basic and simple. It can serve as a sanity check to see if CouchDB is running at all. It can also act as a safety guard for libraries that require a certain version of CouchDB. We\u2019re using the curl utility again:<\/p>\n<pre class=\"brush:bash\">curl http:\/\/127.0.0.1:5984\/<\/pre>\n<p>CouchDB replies, all excited to get going:<\/p>\n<pre class=\"brush:bash\">{\"couchdb\":\"Welcome\",\"version\":\"1.0.1\"}<\/pre>\n<p>We get back a JSON string, which, if parsed into a native object or data structure of our programming language, gives us access to the welcome string and version information.<\/p>\n<p>This is not terribly useful, but it illustrates nicely the way CouchDB behaves. We send an HTTP request and we receive a JSON string in the HTTP response as a result.<\/p>\n<h3><a name=\"Databases\"><\/a>4.1 Databases<\/h3>\n<p>Strictly speaking, CouchDB is a database management system (DMS). That means it can hold multiple databases. A database is a bucket that holds \u201crelated data.\u201d We\u2019ll explore later what that means in detail. In practice, the terminology is overlapping\u2014often people refer to a DMS as \u201ca database\u201d and also a database within the DMS as \u201ca database.\u201d We might follow that slight oddity, so don\u2019t get confused by it. In general, it should be clear from the context if we are talking about the whole of CouchDB or a single database within CouchDB.<\/p>\n<p>Now let\u2019s make one! Note that we\u2019re now using the -X option again to tell curl to send a PUT request instead of the default GET request:<\/p>\n<pre class=\"brush:bash\">curl -X PUT http:\/\/127.0.0.1:5984\/student<\/pre>\n<p>CouchDB replies:<\/p>\n<pre class=\"brush:bash\">{\"ok\":true}<\/pre>\n<p>That\u2019s it. We created a database and CouchDB told us that all went well. What happens if we try to create a database that already exists? Let\u2019s try to create that database again:<\/p>\n<pre class=\"brush:bash\">curl -X PUT http:\/\/127.0.0.1:5984\/student<\/pre>\n<p>CouchDB replies:<\/p>\n<pre class=\"brush:bash\">{\"error\":\"file_exists\",\"reason\":\"The database could not be created, the file already exists.\"}<\/pre>\n<p>We get back an error. This is pretty convenient. CouchDB stores each database in a single file.<\/p>\n<p>Let\u2019s create another database, this time with curl\u2019s -v (for \u201cverbose\u201d) option. The verbose option tells curl to show us not only the essentials\u2014the HTTP response body\u2014but all the underlying request and response details:<\/p>\n<pre class=\"brush:bash\">curl -vX PUT http:\/\/127.0.0.1:5984\/student-backup<\/pre>\n<p>Curl elaborates:<\/p>\n<pre class=\"brush:bash\">* About to connect() to 127.0.0.1 port 5984 (#0)\r\n\r\n*   Trying 127.0.0.1... connected\r\n\r\n&gt; PUT \/student-backup HTTP\/1.1\r\n\r\n&gt; User-Agent: curl\/7.22.0 (x86_64-pc-linux-gnu) libcurl\/7.22.0 OpenSSL\/1.0.1 zlib\/1.2.3.4 libidn\/1.23 librtmp\/2.3\r\n\r\n&gt; Host: 127.0.0.1:5984\r\n\r\n&gt; Accept: *\/*\r\n\r\n&gt;\r\n\r\n&lt; HTTP\/1.1 201 Created\r\n\r\n&lt; Server: CouchDB\/1.0.1 (Erlang OTP\/R14B)\r\n\r\n&lt; Location: http:\/\/127.0.0.1:5984\/student-backup\r\n\r\n&lt; Date: Sat, 15 Feb 2014 17:50:51 GMT\r\n\r\n&lt; Content-Type: text\/plain;charset=utf-8\r\n\r\n&lt; Content-Length: 12\r\n\r\n&lt; Cache-Control: must-revalidate\r\n\r\n&lt;  {\"ok\":true} * Connection #0 to host 127.0.0.1 left intact * Closing connection #0<\/pre>\n<p>Let\u2019s step through this line by line in order to understand what\u2019s going on and find out what\u2019s important. Once we\u2019ve seen this output a few times, we\u2019ll be able to spot the important bits more easily.<\/p>\n<pre class=\"brush:bash\">* About to connect() to 127.0.0.1 port 5984 (#0)<\/pre>\n<p>This is curl telling us that it is going to establish a TCP connection to the CouchDB server we specified in our request URI. Not at all important, except when debugging networking issues.<\/p>\n<pre class=\"brush:bash\">*   Trying 127.0.0.1... connected * Connected to 127.0.0.1 (127.0.0.1) port 5984 (#0)<\/pre>\n<p>Curl tells us it successfully connected to CouchDB. Again, not important if there is no problem with the network. The following lines are prefixed with &gt; and &lt; characters. &gt; means the line was sent to CouchDB verbatim (without the actual &gt;). &lt; means the line was sent back to curl by CouchDB.<\/p>\n<pre class=\"brush:bash\">&gt; PUT \/student-backup HTTP\/1.1<\/pre>\n<p>This initiates an HTTP request. Its method is PUT, the URI is \/student-backup, and the HTTP version is HTTP\/1.1. There is also HTTP\/1.0, which is simpler in some cases, but for all practical reasons We should be using HTTP\/1.1.<\/p>\n<p>Next, we see a number of request headers. These are used to provide additional details about the request to CouchDB.<\/p>\n<pre class=\"brush:bash\">&gt; User-Agent: curl\/7.22.0 (x86_64-pc-linux-gnu) libcurl\/7.22.0 OpenSSL\/1.0.1 zlib\/1.2.3.4 libidn\/1.23 librtmp\/2.3<\/pre>\n<p>The User-Agent header tells CouchDB which piece of client software is doing the HTTP request. It\u2019s the curl program. This header is often useful in web development when there are known errors in client implementations that a server might want to prepare the response for. It also helps to determine which platform a user is on. This information can be used for technical and statistical reasons. For CouchDB, the User-Agent header is not very relevant.<\/p>\n<pre class=\"brush:bash\">&gt; Host: 127.0.0.1:5984<\/pre>\n<p>The Host header is required by HTTP 1.1. It tells the server the hostname that came with the request.<\/p>\n<pre class=\"brush:bash\">&gt; Accept: *\/*<\/pre>\n<p>The Accept header tells CouchDB that curl accepts any media type. We\u2019ll look into why this is useful a little later.<\/p>\n<pre class=\"brush:bash\">&gt;<\/pre>\n<p>An empty line denotes that the request headers are now finished and the rest of the request contains data we\u2019re sending to the server. In this case, we\u2019re not sending any data, so the rest of the curl output is dedicated to the HTTP response.<\/p>\n<pre class=\"brush:bash\">&lt; HTTP\/1.1 201 Created<\/pre>\n<p>The first line of CouchDB\u2019s HTTP response includes the HTTP version information (again, to acknowledge that the requested version could be processed), an HTTP status code, and a status code message. Different requests trigger different response codes. There\u2019s a whole range of them telling the client (curl in our case) what effect the request had on the server. Or, if an error occurred, what kind of error.<\/p>\n<p>RFC 2616 (the HTTP 1.1 specification) defines clear behavior for response codes. CouchDB fully follows the RFC. The 201 Created status code tells the client that the resource the request was made against was successfully created. No surprise here, but if we remember that we got an error message when we tried to create this database twice, we now know that this response could include a different response code.<\/p>\n<p>Acting upon responses based on response codes is a common practice. For example, all response codes of 400 (or greater than that) inform us that some error occurred. If we want to shortcut the logic and immediately deal with the error, we could just check a &gt;= 400 response code.<\/p>\n<pre class=\"brush:bash\">&lt; Server: CouchDB\/0.10.1 (Erlang OTP\/R13B)<\/pre>\n<p>The Server header is good for diagnostics. It tells us which CouchDB version and which underlying Erlang version we are talking to. In general, we can ignore this header, but it is good to know it\u2019s there if We need it.<\/p>\n<pre class=\"brush:bash\">&lt; Date: Sun, 05 Jul 2009 22:48:28 GMT<\/pre>\n<p>The Date header tells the time of the server. Since client and server time are not necessarily synchronized, this header is purely informational. We shouldn\u2019t build any critical application logic on top of this!<\/p>\n<pre class=\"brush:bash\">&lt; Content-Type: text\/plain;charset=utf-8<\/pre>\n<p>The Content-Type header tells which MIME type the HTTP response body uses and what encoding is used for it. We already know that CouchDB returns JSON strings. The appropriate Content-Type header is application\/json. Why do we see text\/plain? This is where pragmatism wins over purity. Sending an application\/json Content-Type header will make a browser offer the returned JSON for download instead of just displaying it. Since it is extremely useful to be able to test CouchDB from a browser, CouchDB sends a text\/plain content type, so all browsers will display the JSON as text.<\/p>\n<p>There are some extensions that make our browser JSON-aware, but they are not installed by default. For more information, look at the popular JSONView extension, available for both Firefox and Chrome.<\/p>\n<p>If we send Accept: application\/json in our request, CouchDB knows that we can deal with a pure JSON response with the proper Content-Type header and will use it instead of text\/plain.<\/p>\n<pre class=\"brush:bash\">&lt; Content-Length: 12<\/pre>\n<p>The Content-Length header simply tells us how many bytes the response body has.<\/p>\n<pre class=\"brush:bash\">&lt; Cache-Control: must-revalidate<\/pre>\n<p>This Cache-Control header tells us, or any proxy server between CouchDB and us, not to cache this response.<\/p>\n<pre class=\"brush:bash\">&lt;<\/pre>\n<p>This empty line tells us we\u2019re done with the response headers and what follows now is the response body.<\/p>\n<pre class=\"brush:bash\">* Connection #0 to host 127.0.0.1 left intact * Closing connection #0<\/pre>\n<p>The last two lines are curl telling us that it kept the TCP connection it opened in the beginning open for a moment, but then closed it after it received the entire response.<\/p>\n<pre class=\"brush:bash\">&gt; curl -vX DELETE http:\/\/127.0.0.1:5984\/albums-backup<\/pre>\n<p>This deletes a CouchDB database. The request will remove the file that the database contents are stored in. We need to use this command with care, as our data will be deleted without a chance to bring it back easily if we don\u2019t have a backup copy.<\/p>\n<p>The console will look like this:<\/p>\n<pre class=\"brush:bash\">* About to connect() to 127.0.0.1 port 5984 (#0)\r\n\r\n*   Trying 127.0.0.1... connected\r\n\r\n&gt; DELETE \/student-backup HTTP\/1.1\r\n\r\n&gt; User-Agent: curl\/7.22.0 (x86_64-pc-linux-gnu) libcurl\/7.22.0 OpenSSL\/1.0.1 zlib\/1.2.3.4 libidn\/1.23 librtmp\/2.3\r\n\r\n&gt; Host: 127.0.0.1:5984\r\n\r\n&gt; Accept: *\/*\r\n\r\n&gt;\r\n\r\n&lt; HTTP\/1.1 200 OK\r\n\r\n&lt; Server: CouchDB\/1.0.1 (Erlang OTP\/R14B)\r\n\r\n&lt; Date: Sat, 15 Feb 2014 17:53:58 GMT\r\n\r\n&lt; Content-Type: text\/plain;charset=utf-8\r\n\r\n&lt; Content-Length: 12\r\n\r\n&lt; Cache-Control: must-revalidate\r\n\r\n&lt;\r\n\r\n{\"ok\":true}\r\n\r\n* Connection #0 to host 127.0.0.1 left intact\r\n\r\n* Closing connection #0\r\n<\/pre>\n<p>This section went knee-deep into HTTP and set the stage for discussing the rest of the core CouchDB API. Next stop: documents.<\/p>\n<h3><a name=\"Documents\"><\/a>4.2 Documents<\/h3>\n<p>Let\u2019s have a closer look at our document creation requests with the curl -v flag that was helpful when we explored the database API earlier. This is also a good opportunity to create more documents that we can use in later examples.<\/p>\n<p>We\u2019ll add some more of our favorite music albums. Get a fresh UUID from the \/_uuids resource. If we don\u2019t remember how that works, w can look it up a few pages back.<\/p>\n<pre class=\"brush:bash\">curl -vX PUT http:\/\/127.0.0.1:5984\/albums\/70b50bfa0a4b3aed1f8aff9e92dc16a0 -d '{\"title\":\"Blackened Sky\",\"artist\":\"Biffy Clyro\",\"year\":2002}'<\/pre>\n<p>Now with the -v option, CouchDB\u2019s reply (with only the important bits shown) looks like this:<\/p>\n<pre class=\"brush:bash\">&gt; PUT \/albums\/70b50bfa0a4b3aed1f8aff9e92dc16a0 HTTP\/1.1\r\n&gt;\r\n&lt; HTTP\/1.1 201 Created\r\n&lt; Location: http:\/\/127.0.0.1:5984\/albums\/70b50bfa0a4b3aed1f8aff9e92dc16a0\r\n&lt; Etag: \"1-2248288203\"\r\n&lt;\r\n{\"ok\":true,\"id\":\"70b50bfa0a4b3aed1f8aff9e92dc16a0\",\"rev\":\"1-2248288203\"}\r\n<\/pre>\n<p>We\u2019re getting back the 201 Created HTTP status code in the response headers, as we saw earlier when we created a database. The Location header gives us a full URL to our newly created document and there\u2019s a new header. An Etag in HTTP-speak identifies a specific version of a resource. In this case, it identifies a specific version (the first one) of our new document. An Etag is the same as a CouchDB document revision number, and it shouldn\u2019t come as a surprise that CouchDB uses revision numbers for Etags. Etags are useful for caching infrastructures.<\/p>\n<h3><a name=\"Attachments\"><\/a>4.3 Attachments<\/h3>\n<p>CouchDB documents can have attachments just like an email message can have attachments. An attachment is identified by a name and includes its MIME type (or Content-Type) and the number of bytes the attachment contains. Attachments can consist of any type of data. It is easier to think about attachments as files attached to a document. These files can be text, images, Word documents, music, or movie files. Let\u2019s make one.<\/p>\n<p>Attachments get their own URL where we can upload data. Let&#8217;s suppose we want to add the album artwork to the 6e1295ed6c29495e54cc05947f18c8af document (\u201cThere is Nothing Left to Lose\u201d), and let\u2019s also say the artwork is in a file artwork.jpg in the current directory:<\/p>\n<pre class=\"brush:bash\">&gt; curl -vX PUT http:\/\/127.0.0.1:5984\/albums\/6e1295ed6c29495e54cc05947f18c8af\/artwork.jpg?rev=2-2739352689 --data-binary @artwork.jpg -H \"Content-Type: image\/jpg\"<\/pre>\n<p>The &#8211;data-binary @ option tells curl to read a file\u2019s contents into the HTTP request body. We\u2019re using the -H option to tell CouchDB that we\u2019re uploading a JPEG file. CouchDB will keep this information around and will send the appropriate header when requesting this attachment; in case of an image like this, a browser will render the image instead of offering the data for download. This will come in handy later. Note that we need to provide the current revision number of the document we\u2019re attaching the artwork to, just as if we would update the document.<\/p>\n<p>If we request the document again, we will see a new member:<\/p>\n<pre class=\"brush:bash\">curl http:\/\/127.0.0.1:5984\/albums\/6e1295ed6c29495e54cc05947f18c8af<\/pre>\n<p>CouchDB replies:<\/p>\n<pre class=\"brush:bash\">{\"_id\":\"6e1295ed6c29495e54cc05947f18c8af\",\"_rev\":\"3-131533518\",\"title\": \"There is Nothing Left to Lose\",\"artist\":\"Foo Fighters\",\"year\":\"1997\",\"_attachments\":{\"artwork.jpg\":{\"stub\":true,\"content_type\":\"image\/jpg\",\"length\":52450}}}<\/pre>\n<p>_attachments is a list of keys and values where the values are JSON objects containing the attachment metadata. stub=true tells us that this entry is just the metadata. If we use the ?attachments=true HTTP option when requesting this document, we\u2019d get a Base64-encoded string containing the attachment data.<\/p>\n<p>We\u2019ll have a look at more document request options later as we explore more features of CouchDB, such as replication, which is the next topic.<\/p>\n<h3><a name=\"Replication\"><\/a>4.4 Replication<\/h3>\n<p>CouchDB replication is a mechanism to synchronize databases. Much like rsync synchronizes two directories locally or over a network, replication synchronizes two databases locally or remotely.<\/p>\n<p>Using a simple POST request, we tell CouchDB the source and the target of a replication and CouchDB will figure out which documents and new document revisions exist on the source DB and they are not yet on the target DB, and will proceed to move the missing documents and revisions over.<\/p>\n<p>First, we\u2019ll create a target database. Note that CouchDB won\u2019t automatically create a target database and will return a replication failure if the target doesn\u2019t exist:<\/p>\n<pre class=\"brush:bash\">curl -X PUT http:\/\/127.0.0.1:5984\/albums-replica<\/pre>\n<p>Now we can use the database albums-replica as a replication target:<\/p>\n<pre class=\"brush:bash\">curl -vX POST http:\/\/127.0.0.1:5984\/_replicate -d '{\"source\":\"albums\",\"target\":\"albums-replica\"}' -H \"Content-Type: application\/json\"<\/pre>\n<p>CouchDB replies (this time we formatted the output so We can read it more easily):<\/p>\n<pre class=\"brush:bash\">{\r\n  \"history\": [\r\n    {\r\n      \"start_last_seq\": 0,\r\n      \"missing_found\": 2,\r\n      \"docs_read\": 2,\r\n      \"end_last_seq\": 5,\r\n      \"missing_checked\": 2,\r\n      \"docs_written\": 2,\r\n      \"doc_write_failures\": 0,\r\n      \"end_time\": \"Sat, 11 Jul 2009 17:36:21 GMT\",\r\n      \"start_time\": \"Sat, 11 Jul 2009 17:36:20 GMT\"\r\n    }\r\n  ],\r\n  \"source_last_seq\": 5,\r\n  \"session_id\": \"924e75e914392343de89c99d29d06671\",\r\n  \"ok\": true\r\n}<\/pre>\n<p>CouchDB maintains a session history of replications. The response for a replication request contains the history entry for this replication session. It is also worth noting that the request for replication will stay open until replication closes. If we have a lot of documents, it\u2019ll take a while until they are all replicated and we won\u2019t get back the replication response until all documents are replicated. It is important to note that replication replicates the database only as it was at the point in time when replication was started. So, any additions, modifications, or deletions subsequent to the start of replication will not be replicated.<\/p>\n<p>We\u2019ll punt on the details again: the &#8220;ok&#8221;: true at the end tells us all went well. If we have a look at the albums-replica database, we should see all the documents that we created in the albums database.<\/p>\n<p>In CouchDB terms, we created a local copy of a database. This is useful for backups or to keep snapshots of a specific state of data around for later.<\/p>\n<p>There are more types of replication useful in other situations. The source and target members of our replication request are actually links (like in HTML) and so far we\u2019ve seen links relative to the server we\u2019re working on (hence local). We can also specify a remote database as the target:<\/p>\n<pre class=\"brush:bash\">curl -vX POST http:\/\/127.0.0.1:5984\/_replicate -d '{\"source\":\"albums\",\"target\":\"http:\/\/example.org:5984\/albums-replica\"}' -H \"Content-Type: application\/json\"<\/pre>\n<p>Using a local source and a remote target database is called push replication. We\u2019re pushing changes to a remote server.<\/p>\n<p>We can also use a remote source and a local target to do a pull replication. This is great for getting the latest changes from a server that is used by others:<\/p>\n<pre class=\"brush:bash\">curl -vX POST http:\/\/127.0.0.1:5984\/_replicate -d '{\"source\":\"http:\/\/example.org:5984\/albums-replica\",\"target\":\"albums\"}' -H \"Content-Type: application\/json\"<\/pre>\n<p>Finally, we can run remote replication, which is mostly useful for management operations:<\/p>\n<pre class=\"brush:bash\">curl -vX POST http:\/\/127.0.0.1:5984\/_replicate -d '{\"source\":\"http:\/\/example.org:5984\/albums\",\"target\":\"http:\/\/example.org:5984\/albums-replica\"}' -H \"Content-Type: application\/json\"<\/pre>\n<h2><a name=\"JSON\"><\/a>5. JSON<\/h2>\n<p>CouchDB uses JavaScript Object Notation (JSON) for data storage. JSON is a lightweight format based on a subset of JavaScript syntax. One of the best bits about JSON is that it\u2019s easy to read and write by hand, much more so than something like XML. We can parse it naturally with JavaScript because it shares part of the same syntax. This really comes in handy when we\u2019re building dynamic web applications and we want to fetch some data from the server.<\/p>\n<p>Here\u2019s a sample JSON document:<\/p>\n<pre class=\"brush:bash\">{\r\n    \"Subject\": \"I like Plankton\",\r\n    \"Author\": \"Rusty\",\r\n    \"PostedDate\": \"2006-08-15T17:30:12-04:00\",\r\n    \"Tags\": [\r\n        \"plankton\",\r\n        \"baseball\",\r\n        \"decisions\"\r\n    ],\r\n    \"Body\": \"I decided today that I don't like baseball. I like plankton.\"\r\n}<\/pre>\n<p>We can see that the general structure is based around key\/value pairs and lists of things.<\/p>\n<h3><a name=\"Data Types\"><\/a>5.1 Data Types<\/h3>\n<p>JSON has a number of basic data types We can use. We\u2019ll cover them all here.<\/p>\n<h3><a name=\"Numbers\"><\/a>5.2 Numbers<\/h3>\n<p>We can have positive integers: &#8220;Count&#8221;: 253<\/p>\n<p>Or negative integers: &#8220;Score&#8221;: -19<\/p>\n<p>Or floating-point numbers: &#8220;Area&#8221;: 456.31<\/p>\n<p>Or scientific notation: &#8220;Density&#8221;: 5.6e+24<\/p>\n<h3><a name=\"Strings\"><\/a>5.3 Strings<\/h3>\n<p>We can use strings for values:<\/p>\n<pre class=\"brush:bash\">\"Author\": \"Rusty\"<\/pre>\n<p>We have to escape some special characters, like tabs or newlines:<\/p>\n<pre class=\"brush:bash\">\"poem\": \"May I compare thee to some\\\\n\\\\tsalty plankton.\"<\/pre>\n<p>The <a href=\"http:\/\/www.json.org\/\">JSON site<\/a> has details on what needs to be escaped.<\/p>\n<h3><a name=\"Booleans\"><\/a>5.4 Booleans<\/h3>\n<p>We can have boolean true values:<\/p>\n<pre class=\"brush:bash\">\"Draft\": true<\/pre>\n<p>Or boolean false values:<\/p>\n<pre class=\"brush:bash\">\"Draft\": false<\/pre>\n<p><strong>Arrays<\/strong><\/p>\n<p>An array is a list of values:<\/p>\n<pre class=\"brush:bash\">\"Tags\": [\"plankton\", \"baseball\", \"decisions\"]<\/pre>\n<p>An array can contain any other data type, including arrays:<\/p>\n<pre class=\"brush:bash\">\"Context\": [\"dog\", [1, true], {\"Location\": \"puddle\"}]<\/pre>\n<p><strong>Objects<\/strong><\/p>\n<p>An object is a list of key\/value pairs:<\/p>\n<pre class=\"brush:bash\">{\"Subject\": \"I like Plankton\", \"Author\": \"Rusty\"}<\/pre>\n<p><strong>Nulls<\/strong><\/p>\n<p>We can have null values:<\/p>\n<pre class=\"brush:bash\">\"Surname\": null<\/pre>\n<h2><a name=\"Document\"><\/a>6. Documents<\/h2>\n<p>Documents are CouchDB\u2019s central data structure. The idea behind a document is, unsurprisingly, that of a real-world document \u2013 a sheet of paper such as an invoice, a recipe, or a business card. We have already learned that CouchDB uses the JSON format to store documents. Let\u2019s see how this storing works at the lowest level.<\/p>\n<p>Each document in CouchDB has an ID. This ID is unique per database. We are free to choose any string to be the ID, but for best results we recommend a UUID (or GUID), i.e., a Universally (or Globally) Unique IDentifier. UUIDs are random numbers that have such a low collision probability. We can make thousands of UUIDs per minute for millions of years without ever creating a duplicate. This is a great way to ensure two independent people cannot create two different documents with the same ID. Why should we care what somebody else is doing? For one, somebody else could be at a later time or on a different computer; secondly, CouchDB replication let&#8217;s us share documents with others and using UUIDs ensures that it all works. But more on that later; let\u2019s make some documents:<\/p>\n<pre class=\"brush:bash\">curl -X PUT http:\/\/127.0.0.1:5984\/shopcart\/6e1295ed6c29495e54cc05947f18c8af -d '{\"title\":\"There is Nothing Left to Lose\",\"artist\":\"Foo Fighters\"}'<\/pre>\n<p>CouchDB replies:<\/p>\n<pre class=\"brush:bash\">{\"ok\":true,\"id\":\"6e1295ed6c29495e54cc05947f18c8af\",\"rev\":\"1-2902191555\"}<\/pre>\n<p>The curl command appears complex, but let\u2019s break it down. First, -X PUT tells curl to make a PUT request. It is followed by the URL that specifies Wer CouchDB IP address and port. The resource part of the URL \/albums\/6e1295ed6c29495e54cc05947f18c8af specifies the location of a document inside our albums database. The wild collection of numbers and characters is a UUID. This UUID is Wer document\u2019s ID. Finally, the -d flag tells curl to use the following string as the body for the PUT request. The string is a simple JSON structure including title and artist attributes with their respective values.<\/p>\n<p>A CouchDB document is simply a JSON object. We can use any JSON structure with nesting. We can fetch the document&#8217;s revision information by adding ?revs_info=true to the get request.<\/p>\n<p>To get a UUID, we use:<\/p>\n<pre class=\"brush:bash\">curl -X GET http:\/\/127.0.0.1:5984\/_uuids<\/pre>\n<p>CouchDb will reply us back, like this:<\/p>\n<pre class=\"brush:bash\">{\"uuids\":[\"6e1295ed6c29495e54cc05947f18c8af\"]}<\/pre>\n<p>Here are two simple examples of documents:<\/p>\n<pre class=\"brush:bash\">{\r\n \"_id\":\"discussion_tables\",\r\n \"_rev\":\"D1C946B7\",\r\n \"Sunrise\":true,\r\n \"Sunset\":false,\r\n \"FullHours\":[1,2,3,4,5,6,7,8,9,10],\r\n \"Activities\": [\r\n   {\"Name\":\"Football\", \"Duration\":2, \"DurationUnit\":\"Hours\"},\r\n   {\"Name\":\"Breakfast\", \"Duration\":40, \"DurationUnit\":\"Minutes\", \"Attendees\":[\"Jan\", \"Damien\", \"Laura\", \"Gwendolyn\", \"Roseanna\"]}\r\n ]\r\n}<\/pre>\n<pre class=\"brush:bash\">{\r\n \"_id\":\"some_doc_id\",\r\n \"_rev\":\"D1C946B7\",\r\n \"Subject\":\"I like Plankton\",\r\n \"Author\":\"Rusty\",\r\n \"PostedDate\":\"2006-08-15T17:30:12-04:00\",\r\n \"Tags\":[\"plankton\", \"baseball\", \"decisions\"],\r\n \"Body\":\"I decided today that I don't like baseball. I like plankton.\"\r\n}<\/pre>\n<h3><a name=\"Special Fields\"><\/a>6.1 Special Fields<\/h3>\n<p>Note that any top-level fields within a JSON document containing a name that starts with a _ prefix are reserved for use by CouchDB itself. Also see Reserved_words. Currently (0.10+) reserved fields are:<\/p>\n<div class=\"wp-caption aligncenter\">\n<table border=\"0\" cellspacing=\"0\" cellpadding=\"0\">\n<tbody>\n<tr>\n<td width=\"110\"><strong>Field Name<\/strong><\/td>\n<td width=\"533\"><strong>Description<\/strong><em><\/em><\/td>\n<\/tr>\n<tr>\n<td width=\"110\"><em> <\/em><em>_id<\/em><\/td>\n<td width=\"533\">The unique identifier of the document (<strong>mandatory <\/strong>and <strong>immutable<\/strong>)<em><\/em><\/td>\n<\/tr>\n<tr>\n<td width=\"110\"><em>_rev<\/em><\/td>\n<td width=\"533\">The current MVCC-token\/revision of this document (<strong>mandatory <\/strong>and <strong>immutable<\/strong>)<em><\/em><\/td>\n<\/tr>\n<tr>\n<td width=\"110\"><em>_attachments<\/em><\/td>\n<td width=\"533\">If the document has attachments, _attachments holds a (meta-)data structure (see section on <a href=\"http:\/\/wiki.apache.org\/couchdb\/HTTP_Document_API#Attachments\">HTTP_Document_API#Attachments<\/a>)<em><\/em><\/td>\n<\/tr>\n<tr>\n<td width=\"110\"><em>_deleted<\/em><\/td>\n<td width=\"533\">Indicates that this document has been deleted and previous revisions will be removed on next compaction run<em><\/em><\/td>\n<\/tr>\n<tr>\n<td width=\"110\"><em>_revisions<\/em><\/td>\n<td width=\"533\">Revision history of the document<em><\/em><\/td>\n<\/tr>\n<tr>\n<td width=\"110\"><em>_revs_info<\/em><\/td>\n<td width=\"533\">A list of revisions of the document, and their availability<em><\/em><\/td>\n<\/tr>\n<tr>\n<td width=\"110\"><em>_conflicts<\/em><\/td>\n<td width=\"533\">Information about conflicts<em><\/em><\/td>\n<\/tr>\n<tr>\n<td width=\"110\"><em>_deleted_conflicts<\/em><\/td>\n<td width=\"533\">Information about conflicts<em><\/em><\/td>\n<\/tr>\n<tr>\n<td width=\"110\"><em>_local_seq<\/em><\/td>\n<td width=\"533\">Sequence number of the revision in the database (as found in the _changes feed)<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p class=\"wp-caption-text\">Table 1<\/p>\n<\/div>\n<p>To request a special field to be returned along with the normal fields we get when we request a document, add the desired field as a query parameter without the leading underscore in a GET request:<\/p>\n<pre class=\"brush:bash\">curl -X GET 'http:\/\/localhost:5984\/my_database\/my_document?conflicts=true'<\/pre>\n<p>This request will return a document that includes the special field &#8216;_conflicts&#8217; which contains all the conflicting revisions of &#8220;my_document&#8221;.<\/p>\n<p>[<strong>Exception:<\/strong> The query parameter for the <em>_revisions<\/em> special field is &#8216;revs&#8217;, not &#8216;revisions&#8217;.]<\/p>\n<h3><a name=\"Document IDs\"><\/a>6.2 Document IDs<\/h3>\n<p>Document IDs don&#8217;t have restrictions on what characters can be used. Although it should work, it is recommended to use non-special characters for document IDs. By using special characters, we have to be aware of proper URL en-\/decoding. Documents prefixed with <em>_<\/em> are special documents:<strong><\/strong><\/p>\n<div class=\"wp-caption aligncenter\">\n<table border=\"0\" cellspacing=\"0\" cellpadding=\"0\">\n<tbody>\n<tr>\n<td width=\"138\"><strong>Document ID prefix<\/strong><\/td>\n<td width=\"505\"><strong>Description<\/strong><em><\/em><\/td>\n<\/tr>\n<tr>\n<td width=\"138\"><em>_design\/<\/em><\/td>\n<td width=\"505\">are <a href=\"http:\/\/wiki.apache.org\/couchdb\/DesignDocuments\">DesignDocuments<\/a><em><\/em><\/td>\n<\/tr>\n<tr>\n<td width=\"138\"><em>_local\/<\/em><strong><\/strong><\/td>\n<td width=\"505\">are not being replicated (local documents) and used for <a href=\"http:\/\/wiki.apache.org\/couchdb\/Replication\">Replication<\/a> checkpointing.<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p class=\"wp-caption-text\">Table 2<\/p>\n<\/div>\n<p>We can have \/ as part of the document ID but if We refer to a document in a URL We must always encode it as %2F. One special case is _design\/ documents, those accept either \/ or %2F for the \/ after <em>_design<\/em>, although \/ is preferred and %2F is still needed for the rest of the DocID.<\/p>\n<h3><a name=\"Working With Documents Over HTTP\"><\/a>6.3 Working With Documents Over HTTP<\/h3>\n<p><strong>GET<\/strong><\/p>\n<p>To retrieve a document, simply perform a <em>GET<\/em> operation at the document&#8217;s URL:<\/p>\n<pre class=\"brush:bash\">curl -X GET http:\/\/127.0.0.1:5984\/shopcart\/6e1295ed6c29495e54cc05947f18c8af<\/pre>\n<p>Here is the server&#8217;s response:<\/p>\n<pre class=\"brush:bash\">{\"_id\":\"6e1295ed6c29495e54cc05947f18c8af\",\"_rev\":\"1-4b39c2971c9ad54cb37e08fa02fec636\",\"title\":\"There is Nothing Left to Lose\",\"artist\":\"Foo Fighters\"}<\/pre>\n<h2><a name=\"Revisions\"><\/a>7. Revisions<\/h2>\n<p>If we want to change a document in CouchDB, we don\u2019t tell it to go and find a field in a specific document and insert a new value. Instead, we load the full document out of CouchDB, make our changes in the JSON structure (or object, when we are doing actual programming), and save the entire new revision (or version) of that document back into CouchDB. Each revision is identified by a new <i>_rev <\/i>value.<\/p>\n<p>If we want to update or delete a document, CouchDB expects us to include the<i>_rev <\/i>field of the revision we wish to change. When CouchDB accepts the change, it will generate a new revision number. This mechanism ensures that, in case somebody else made a change without us knowing before we got to request the document update, CouchDB will not accept our update because we are likely to overwrite data we didn\u2019t know that even existed. Or simplified: whoever saves a change to a document first, wins. Let\u2019s see what happens if we don\u2019t provide a <i>_rev <\/i>field (which is equivalent to providing a outdated value):<b><\/b><\/p>\n<pre class=\"brush:bash\">curl -X PUT http:\/\/127.0.0.1:5984\/shopcart\/6e1295ed6c29495e54cc05947f18c8af -d '{\"title\":\"There is Nothing Left to Lose\",\"artist\":\"Foo Fighters\",\"year\":\"1997\"}'<\/pre>\n<p>CouchDB replies:<\/p>\n<pre class=\"brush:bash\">{\"error\":\"conflict\",\"reason\":\"Document update conflict.\"}<\/pre>\n<p>If we see this, add the latest revision number of your document to the JSON structure:<b><\/b><\/p>\n<pre class=\"brush:bash\">curl -X PUT http:\/\/127.0.0.1:5984\/shopcart\/6e1295ed6c29495e54cc05947f18c8af -d '{\"_rev\":\"1-2902191555\",\"title\":\"There is Nothing Left to Lose\", \"artist\":\"Foo Fighters\",\"year\":\"1997\"}'<\/pre>\n<p>Now we see why it was handy that CouchDB returned that <i>_rev<\/i> when we made the initial request. CouchDB replies:<\/p>\n<pre class=\"brush:bash\">{\"ok\":true,\"id\":\"6e1295ed6c29495e54cc05947f18c8af\",\"rev\":\"2-2739352689\"}<\/pre>\n<h3><a name=\"Accessing Previous\"><\/a>7.1 Accessing Previous Revisions<\/h3>\n<p>The above example gets the current revision. We may be able to get a specific revision by using the following syntax:<\/p>\n<pre class=\"brush:bash\">GET \/somedatabase\/some_doc_id?rev=946B7D1C HTTP\/1.0<\/pre>\n<p>To find out what revisions are available for a document, we can do:<\/p>\n<pre class=\"brush:bash\">GET \/somedatabase\/some_doc_id?revs_info=true HTTP\/1.0<\/pre>\n<p>This returns the current revision of the document, but with an additional <em>_revs_info<\/em> field, whose value is an array of objects, one per revision. For example:<\/p>\n<pre class=\"brush:bash\">{\r\n  \"_revs_info\": [\r\n    {\"rev\": \"3-ffffff\", \"status\": \"available\"},\r\n    {\"rev\": \"2-eeeeee\", \"status\": \"missing\"},\r\n    {\"rev\": \"1-dddddd\", \"status\": \"deleted\"},\r\n  ]\r\n}<\/pre>\n<p>Here, <em>available <\/em>means the revision content is stored in the database and can still be retrieved. The other values indicate that the content of that revision is not available.<\/p>\n<p>Alternatively, the _revisions field, used by the replicator, can return an array of revision IDs more efficiently. The numeric prefixes are removed, with a &#8220;start&#8221; value indicating the prefix for the first (most recent) ID:<\/p>\n<pre class=\"brush:bash\">{\r\n  \"_revisions\": {\r\n    \"start\": 3,\r\n    \"ids\": [\"fffff\", \"eeeee\", \"ddddd\"]\r\n  }\r\n}<\/pre>\n<p>We can fetch the bodies of multiple revisions at once using the parameter open_revs=[&#8220;rev1&#8243;,&#8221;rev2&#8221;,&#8230;], or We can fetch all leaf revisions using open_revs=all. The JSON returns an array of objects with an &#8220;ok&#8221; key pointing to the document, or a &#8220;missing&#8221; key pointing to the rev string.<\/p>\n<pre class=\"brush:bash\">[\r\n{\"missing\":\"1-fbd8a6da4d669ae4b909fcdb42bb2bfd\"},\r\n{\"ok\":{\"_id\":\"test\",\"_rev\":\"2-5bc3c6319edf62d4c624277fdd0ae191\",\"hello\":\"foo\"}}\r\n]<\/pre>\n<h3><a name=\"HEAD\"><\/a>7.2 HEAD<\/h3>\n<p>A HEAD request returns basic information about the document, including its current revision.<\/p>\n<pre class=\"brush:bash\">HEAD \/somedatabase\/some_doc_id HTTP\/1.0\r\nHTTP\/1.1 200 OK\r\nEtag: \"946B7D1C\"\r\nDate: Thu, 17 Aug 2006 05:39:28 +0000GMT\r\nContent-Type: application\/json\r\nContent-Length: 256<\/pre>\n<h3><a name=\"PUT\"><\/a>7.3 PUT<\/h3>\n<p>To create new document we can either use a <em>POST <\/em>operation or a <em>PUT <\/em>operation. To create\/update a named document using the PUT operation, the URL must point to the document&#8217;s location.<\/p>\n<p>The following is an example HTTP <em>PUT<\/em>. It will cause the CouchDB server to generate a new revision ID and save the document with it.<\/p>\n<pre class=\"brush:bash\">PUT \/somedatabase\/some_doc_id HTTP\/1.0\r\nContent-Length: 245\r\nContent-Type: application\/json\r\n\r\n{\r\n  \"Subject\":\"I like Plankton\",\r\n  \"Author\":\"Rusty\",\r\n  \"PostedDate\":\"2006-08-15T17:30:12-04:00\",\r\n  \"Tags\":[\"plankton\", \"baseball\", \"decisions\"],\r\n  \"Body\":\"I decided today that I don't like baseball. I like plankton.\"\r\n}<\/pre>\n<p>Here is the server&#8217;s response.<\/p>\n<pre class=\"brush:bash\">HTTP\/1.1 201 Created\r\nEtag: \"946B7D1C\"\r\nDate: Thu, 17 Aug 2006 05:39:28 +0000GMT\r\nContent-Type: application\/json\r\nConnection: close\r\n\r\n{\"ok\": true, \"id\": \"some_doc_id\", \"rev\": \"946B7D1C\"}\r\n<\/pre>\n<p>To update an existing document, we also issue a <em>PUT<\/em>request. In this case, the JSON body must contain a <em>_rev <\/em>property, which lets CouchDB know which revision the edits are based on. If the revision of the document currently stored in the database doesn&#8217;t match, then a <em>409 <\/em>conflict error is returned.<\/p>\n<p>If the revision number does match what&#8217;s in the database, a new revision number is generated and returned to the client.<\/p>\n<p>For example:<\/p>\n<pre class=\"brush:bash\">PUT \/somedatabase\/some_doc_id HTTP\/1.0\r\nContent-Length: 245\r\nContent-Type: application\/json\r\n\r\n{\r\n  \"_id\":\"some_doc_id\",\r\n  \"_rev\":\"946B7D1C\",\r\n  \"Subject\":\"I like Plankton\",\r\n  \"Author\":\"Rusty\",\r\n  \"PostedDate\":\"2006-08-15T17:30:12-04:00\",\r\n  \"Tags\":[\"plankton\", \"baseball\", \"decisions\"],\r\n  \"Body\":\"I decided today that I don't like baseball. I like plankton.\"\r\n}<\/pre>\n<p>Here is the server&#8217;s response if what is stored in the database is a revision <em>946B7D1C<\/em> of document <em>some_doc_id<\/em>.<\/p>\n<pre class=\"brush:bash\">HTTP\/1.1 201 Created\r\nEtag: \"2774761002\"\r\nDate: Thu, 17 Aug 2006 05:39:28 +0000GMT\r\nContent-Type: application\/json\r\nConnection: close\r\n\r\n{\"ok\":true, \"id\":\"some_doc_id\", \"rev\":\"2774761002\"}<\/pre>\n<p>And here is the server&#8217;s response if there is an update conflict (what is currently stored in the database is not revision <em>946B7D1C <\/em>of document <em>some_doc_id<\/em>).<\/p>\n<pre class=\"brush:bash\">HTTP\/1.1 409 Conflict\r\nDate: Thu, 17 Aug 2006 05:39:28 +0000GMT\r\nContent-Length: 33\r\nConnection: close\r\n\r\n{\"error\":\"conflict\",\"reason\":\"Document update conflict.\"}<\/pre>\n<p>There is a query option <em>batch=ok<\/em>which can be used to achieve higher throughput at the cost of lower guarantees. When a <em>PUT<\/em>(or a document <em>POST<\/em>as described below) is sent using this option, it is not immediately written to disk. Instead it is stored in memory on a per-user basis for a second or so (or the number of docs in memory reaches a certain point). After the threshold has passed, the docs are committed to disk. Instead of waiting for the doc to be written to disk before responding, CouchDB sends an HTTP <em>202 Accepted <\/em>response immediately.<em><\/em><\/p>\n<p><em>batch=ok <\/em>is not suitable for crucial data, but it ideal for applications like logging which can accept the risk that a small proportion of updates could be lost due to a crash. Docs in the batch can also be flushed manually using the <em>_ensure_full_commit <\/em>API.<\/p>\n<h3><a name=\"POST\"><\/a>7.4 POST<\/h3>\n<p>The <em>POST<\/em>operation can be used to create a new document with a server generated DocID. To do so, the URL must point to the database&#8217;s location. To create a named document, use the <em>PUT<\/em>method instead.<\/p>\n<p>It is recommended that we avoid <em>POST<\/em>when possible, because proxies and other network intermediaries will occasionally resend <em>POST<\/em>requests, which can result in duplicate document creation. If our client software is not capable of guaranteeing uniqueness of generated UUIDs, use a <em>GET<\/em>to <em>\/_uuids?count=100<\/em>to retrieve a list of document IDs for future <em>PUT<\/em> requests. Please note that the <em>\/_uuids<\/em>-call does not check for existing document ids; collision-detection happens when We are trying to save a document.<\/p>\n<p>The following is an example HTTP <em>POST<\/em>. It will cause the CouchDB server to generate a new DocID and revision ID and save the document with it.<\/p>\n<pre class=\"brush:bash\">POST \/somedatabase\/ HTTP\/1.0\r\nContent-Length: 245\r\nContent-Type: application\/json\r\n\r\n{\r\n  \"Subject\":\"I like Plankton\",\r\n  \"Author\":\"Rusty\",\r\n  \"PostedDate\":\"2006-08-15T17:30:12-04:00\",\r\n  \"Tags\":[\"plankton\", \"baseball\", \"decisions\"],\r\n  \"Body\":\"I decided today that I don't like baseball. I like plankton.\"\r\n}\r\n<\/pre>\n<p>Here is the server&#8217;s response:<\/p>\n<pre class=\"brush:bash\">HTTP\/1.1 201 Created\r\nDate: Thu, 17 Aug 2006 05:39:28 +0000GMT\r\nContent-Type: application\/json\r\nConnection: close\r\n\r\n{\"ok\":true, \"id\":\"123BAC\", \"rev\":\"946B7D1C\"}<\/pre>\n<p>As of 0.11 CouchDB supports handling of multipart\/form-data encoded updates. This is used by Futon and not considered a public API. All such requests must contain a valid Referer header.<\/p>\n<h3><a name=\"DELETE\"><\/a>7.5 DELETE<\/h3>\n<p>To delete a document, perform a <em>DELETE<\/em> operation at the document&#8217;s location, passing the <em>rev<\/em> parameter with the document&#8217;s current revision. If successful, it will return the revision id for the deletion stub.<\/p>\n<pre class=\"brush:bash\">DELETE \/somedatabase\/some_doc?rev=1582603387 HTTP\/1.0<\/pre>\n<p>As an alternative we can submit the <em>rev<\/em> parameter with the etag header field <em>If-Match<\/em>.<\/p>\n<pre class=\"brush:bash\">DELETE \/somedatabase\/some_doc HTTP\/1.0\r\nIf-Match: \"1582603387\"<\/pre>\n<p>And the response:<\/p>\n<pre class=\"brush:bash\">HTTP\/1.1 200 OK\r\nEtag: \"2839830636\"\r\nDate: Thu, 17 Aug 2006 05:39:28 +0000GMT\r\nContent-Type: application\/json\r\nConnection: close\r\n\r\n{\"ok\":true,\"rev\":\"2839830636\"}<\/pre>\n<p>Note: Deleted documents remain in the database forever, even after compaction, to allow eventual consistency when replicating. If we delete using the DELETE method above, only the _id, _rev and a deleted flag are preserved. If we deleted a document by adding &#8220;_deleted&#8221;:true then all the fields of the document are preserved. This is to allow, for example, to record the time we deleted a document, or the reason we deleted it.<\/p>\n<h3><a name=\"COPY\"><\/a>7.6 COPY<\/h3>\n<p>Note that this is a non-standard extension to HTTP.<\/p>\n<p>We can copy documents by sending an HTTP COPY request. This allows us to duplicate the contents (and attachments) of a document to a new document under a different document id without first retrieving it from CouchDB. Use the <em>Destination<\/em> header to specify the document that We want to copy to (the target document).<\/p>\n<p>It is not possible to copy documents between databases and it is not (yet) possible to perform bulk copy operations.<\/p>\n<pre class=\"brush:bash\">COPY \/somedatabase\/some_doc HTTP\/1.1\r\nDestination: some_other_doc\r\n<\/pre>\n<p>If we want to overwrite an existing document, we need to specify the target document&#8217;s revision with a <em>rev<\/em> parameter in the <em>Destination<\/em> header:<\/p>\n<pre class=\"brush:bash\">COPY \/somedatabase\/some_doc HTTP\/1.1\r\nDestination: some_other_doc?rev=rev_id<\/pre>\n<p>The response in both cases includes the target document&#8217;s revision:<\/p>\n<pre class=\"brush:bash\">HTTP\/1.1 201 Created\r\nServer: CouchDB\/0.9.0a730122-incubating (Erlang OTP\/R12B)\r\nEtag: \"355068078\"\r\nDate: Mon, 05 Jan 2009 11:12:49 GMT\r\nContent-Type: text\/plain;charset=utf-8\r\nContent-Length: 41\r\nCache-Control: must-revalidate\r\n\r\n{\"ok\":true,\"id\":\"some_other_doc\",\"rev\":\"355068078\"}<\/pre>\n<h3><a name=\"All Documents\"><\/a>7.7 All Documents<\/h3>\n<h4>7.6.1 all_docs<\/h4>\n<p>To get a listing of all documents in a database, use the special <em>_all_docs<\/em> URI. This is a specialized View so the Querying Options of the <a href=\"http:\/\/wiki.apache.org\/couchdb\/HTTP_view_API\">HTTP_view_API<\/a> apply here.<\/p>\n<pre class=\"brush:bash\">GET \/somedatabase\/_all_docs HTTP\/1.0<\/pre>\n<p>This will return a listing of all documents and their revision IDs, ordered by DocID (case sensitive):<\/p>\n<pre class=\"brush:bash\">HTTP\/1.1 200 OK\r\nDate: Thu, 17 Aug 2006 05:39:28 +0000GMT\r\nContent-Type: application\/json\r\nConnection: close\r\n\r\n{\r\n  \"total_rows\": 3, \"offset\": 0, \"rows\": [\r\n    {\"id\": \"doc1\", \"key\": \"doc1\", \"value\": {\"rev\": \"4324BB\"}},\r\n    {\"id\": \"doc2\", \"key\": \"doc2\", \"value\": {\"rev\":\"2441HF\"}},\r\n    {\"id\": \"doc3\", \"key\": \"doc3\", \"value\": {\"rev\":\"74EC24\"}}\r\n  ]\r\n}<\/pre>\n<p>Use the query argument <em>descending=true<\/em> to reverse the order of the output table:<\/p>\n<p>Will return the same as before but in reverse order:<\/p>\n<pre class=\"brush:bash\">HTTP\/1.1 200 OK\r\nDate: Thu, 17 Aug 2006 05:39:28 +0000GMT\r\nContent-Type: application\/json\r\nConnection: close\r\n\r\n{\r\n  \"total_rows\": 3, \"offset\": 0, \"rows\": [\r\n    {\"id\": \"doc3\", \"key\": \"doc3\", \"value\": {\"rev\":\"74EC24\"}},\r\n    {\"id\": \"doc2\", \"key\": \"doc2\", \"value\": {\"rev\":\"2441HF\"}},\r\n    {\"id\": \"doc1\", \"key\": \"doc1\", \"value\": {\"rev\": \"4324BB\"}}\r\n  ]\r\n}\r\n<\/pre>\n<p>The query string parameters <em>startkey<\/em>, <em>endkey<\/em> and <em>limit<\/em> may also be used to limit the result set. For example:<\/p>\n<pre class=\"brush:bash\">GET \/somedatabase\/_all_docs?startkey=\"doc2\"&amp;amp;limit=2 HTTP\/1.0<\/pre>\n<p>Will return:<\/p>\n<pre class=\"brush:bash\">HTTP\/1.1 200 OK\r\nDate: Thu, 17 Aug 2006 05:39:28 +0000GMT\r\nContent-Type: application\/json\r\nConnection: close\r\n\r\n{\r\n  \"total_rows\": 3, \"offset\": 1, \"rows\": [\r\n    {\"id\": \"doc2\", \"key\": \"doc2\", \"value\": {\"rev\":\"2441HF\"}},\r\n    {\"id\": \"doc3\", \"key\": \"doc3\", \"value\": {\"rev\":\"74EC24\"}}\r\n  ]\r\n}\r\n<\/pre>\n<p>Use <em>endkey<\/em> if you are interested in a specific range of documents:<\/p>\n<pre class=\"brush:bash\">GET \/somedatabase\/_all_docs?startkey=\"doc2\"&amp;amp;endkey=\"doc3\" HTTP\/1.0<\/pre>\n<p>This will get keys inbetween and including doc2 and doc3; e.g. <em>doc2-b<\/em> and <em>doc234<\/em>.<\/p>\n<p>Both approaches can be combined with <em>descending<\/em>:<\/p>\n<pre class=\"brush:bash\">GET \/somedatabase\/_all_docs?startkey=\"doc2\"&amp;amp;limit=2&amp;amp;descending=true HTTP\/1.0<\/pre>\n<p>Will return:<\/p>\n<pre class=\"brush:bash\">HTTP\/1.1 200 OK\r\nDate: Thu, 17 Aug 2006 05:39:28 +0000GMT\r\nContent-Type: application\/json\r\nConnection: close\r\n\r\n{\r\n  \"total_rows\": 3, \"offset\": 1, \"rows\": [\r\n    {\"id\": \"doc3\", \"key\": \"doc3\", \"value\": {\"rev\":\"74EC24\"}},\r\n    {\"id\": \"doc2\", \"key\": \"doc2\", \"value\": {\"rev\":\"2441HF\"}}\r\n  ]\r\n}<\/pre>\n<p>If we add <em>include_docs=true<\/em> to a request to <em>_all_docs<\/em> not only metadata but also the documents themselves are returned.<\/p>\n<h4>7.6.2 _changes<\/h4>\n<p>This allows us to see all the documents that were updated and deleted, in the order these actions are done:<\/p>\n<pre class=\"brush:bash\">GET \/somedatabase\/_changes HTTP\/1.0<\/pre>\n<p>Will return something of the form:<\/p>\n<pre class=\"brush:bash\">HTTP\/1.1 200 OK\r\nDate: Fri, 8 May 2009 11:07:02 +0000GMT\r\nContent-Type: application\/json\r\nConnection: close\r\n\r\n{\"results\":[\r\n{\"seq\":1,\"id\":\"fresh\",\"changes\":[{\"rev\":\"1-967a00dff5e02add41819138abb3284d\"}]},\r\n{\"seq\":3,\"id\":\"updated\",\"changes\":[{\"rev\":\"2-7051cbe5c8faecd085a3fa619e6e6337\"}]},\r\n{\"seq\":5,\"id\":\"deleted\",\"changes\":[{\"rev\":\"2-eec205a9d413992850a6e32678485900\"}],\"deleted\":true}\r\n],\r\n\"last_seq\":5}<\/pre>\n<p>All the view parameters work on _changes, such as startkey, include_docs etc. However, note that the startkey is exclusive when applied to this view. This allows for a usage pattern where the startkey is set to the sequence id of the last doc returned by the previous query. As the startkey is exclusive, the same document won&#8217;t be processed twice.<\/p>\n<h2><a name=\"http:\/\/guide.couchdb.org\/draft\/api.html#replication\"><\/a>8. Replication<\/h2>\n<p>CouchDB replication is a mechanism to synchronize databases. Much like <i>rsync<\/i>synchronizes two directories locally or over a network, replication synchronizes two databases locally or remotely.<\/p>\n<p>In a simple POST request, we tell CouchDB the <em>source<\/em> and the <em>target<\/em> of a replication and CouchDB will figure out which documents and new document revisions are on <em>source<\/em> that are not yet on <em>target<\/em>, and will proceed to move the missing documents and revisions over.<\/p>\n<p>First, we will create a target database. Note that CouchDB would not automatically create a target database for us, and will return a replication failure if the target doesn\u2019t exist:<\/p>\n<pre class=\"brush:bash\">curl -X PUT http:\/\/127.0.0.1:5984\/shopcart-replica<\/pre>\n<p>Now we can use the database <i>albums-replica<\/i> as a replication target:<\/p>\n<pre class=\"brush:bash\">curl -vX POST http:\/\/127.0.0.1:5984\/_replicate -d '{\"source\":\"shopcart\",\"target\":\"shopcart-replica\"}' -H \"Content-Type: application\/json\"<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>This article is part of our Academy Course titled CouchDB \u2013 Database for the Web. This is a hands-on course on CouchDB. You will learn how to install and configure CouchDB and how to perform common operations with it. Additionally, you will build an example application from scratch and then finish the course with more &hellip;<\/p>\n","protected":false},"author":18,"featured_media":7450,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[8],"tags":[108],"class_list":["post-7470","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-web-development","tag-databases"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v26.5 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>CouchDB: Basics and Operations - Web Code Geeks - 2026<\/title>\n<meta name=\"description\" content=\"This article is part of our Academy Course titled CouchDB \u2013 Database for the Web. This is a hands-on course on CouchDB. You will learn how to install and\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.webcodegeeks.com\/web-development\/couchdb-basics-and-operations\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"CouchDB: Basics and Operations - Web Code Geeks - 2026\" \/>\n<meta property=\"og:description\" content=\"This article is part of our Academy Course titled CouchDB \u2013 Database for the Web. This is a hands-on course on CouchDB. You will learn how to install and\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.webcodegeeks.com\/web-development\/couchdb-basics-and-operations\/\" \/>\n<meta property=\"og:site_name\" content=\"Web Code Geeks\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/webcodegeeks\" \/>\n<meta property=\"article:author\" content=\"http:\/\/www.facebook.com\/phlocblogger\" \/>\n<meta property=\"article:published_time\" content=\"2015-09-28T18:11:24+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2018-01-05T14:53:10+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2015\/09\/couchdb-logo-.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"150\" \/>\n\t<meta property=\"og:image:height\" content=\"150\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Piyas De\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@https:\/\/twitter.com\/phloxblog\" \/>\n<meta name=\"twitter:site\" content=\"@webcodegeeks\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Piyas De\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"40 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.webcodegeeks.com\/web-development\/couchdb-basics-and-operations\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/web-development\/couchdb-basics-and-operations\/\"},\"author\":{\"name\":\"Piyas De\",\"@id\":\"https:\/\/www.webcodegeeks.com\/#\/schema\/person\/7aab6e040a06f0dfe0d60c27768aa424\"},\"headline\":\"CouchDB: Basics and Operations\",\"datePublished\":\"2015-09-28T18:11:24+00:00\",\"dateModified\":\"2018-01-05T14:53:10+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/web-development\/couchdb-basics-and-operations\/\"},\"wordCount\":6553,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/#organization\"},\"image\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/web-development\/couchdb-basics-and-operations\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2015\/09\/couchdb-logo-.jpg\",\"keywords\":[\"Databases\"],\"articleSection\":[\"Web Dev\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.webcodegeeks.com\/web-development\/couchdb-basics-and-operations\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.webcodegeeks.com\/web-development\/couchdb-basics-and-operations\/\",\"url\":\"https:\/\/www.webcodegeeks.com\/web-development\/couchdb-basics-and-operations\/\",\"name\":\"CouchDB: Basics and Operations - Web Code Geeks - 2026\",\"isPartOf\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/web-development\/couchdb-basics-and-operations\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/web-development\/couchdb-basics-and-operations\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2015\/09\/couchdb-logo-.jpg\",\"datePublished\":\"2015-09-28T18:11:24+00:00\",\"dateModified\":\"2018-01-05T14:53:10+00:00\",\"description\":\"This article is part of our Academy Course titled CouchDB \u2013 Database for the Web. This is a hands-on course on CouchDB. You will learn how to install and\",\"breadcrumb\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/web-development\/couchdb-basics-and-operations\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.webcodegeeks.com\/web-development\/couchdb-basics-and-operations\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.webcodegeeks.com\/web-development\/couchdb-basics-and-operations\/#primaryimage\",\"url\":\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2015\/09\/couchdb-logo-.jpg\",\"contentUrl\":\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2015\/09\/couchdb-logo-.jpg\",\"width\":150,\"height\":150},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.webcodegeeks.com\/web-development\/couchdb-basics-and-operations\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.webcodegeeks.com\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Web Dev\",\"item\":\"https:\/\/www.webcodegeeks.com\/category\/web-development\/\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"CouchDB: Basics and Operations\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.webcodegeeks.com\/#website\",\"url\":\"https:\/\/www.webcodegeeks.com\/\",\"name\":\"Web Code Geeks\",\"description\":\"Web Developers Resource Center\",\"publisher\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.webcodegeeks.com\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.webcodegeeks.com\/#organization\",\"name\":\"Exelixis Media P.C.\",\"url\":\"https:\/\/www.webcodegeeks.com\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.webcodegeeks.com\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png\",\"contentUrl\":\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png\",\"width\":864,\"height\":246,\"caption\":\"Exelixis Media P.C.\"},\"image\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/www.facebook.com\/webcodegeeks\",\"https:\/\/x.com\/webcodegeeks\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.webcodegeeks.com\/#\/schema\/person\/7aab6e040a06f0dfe0d60c27768aa424\",\"name\":\"Piyas De\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.webcodegeeks.com\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/eadd6728b7b5be23f0d6585da1a953926e49c6f2369703d6cb4f1147d4dd2203?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/eadd6728b7b5be23f0d6585da1a953926e49c6f2369703d6cb4f1147d4dd2203?s=96&d=mm&r=g\",\"caption\":\"Piyas De\"},\"description\":\"Piyas is Sun Microsystems certified Enterprise Architect with 10+ years of professional IT experience in various areas such as Architecture Definition, Define Enterprise Application, Client-server\/e-business solutions.Currently he is engaged in providing solutions for digital asset management in media companies.He is also founder and main author of \\\"Technical Blogs (Blog about small technical Know hows)\\\"\",\"sameAs\":[\"http:\/\/www.phloxblog.in\",\"http:\/\/www.facebook.com\/phlocblogger\",\"http:\/\/in.linkedin.com\/in\/piyasde\",\"https:\/\/x.com\/https:\/\/twitter.com\/phloxblog\"],\"url\":\"https:\/\/www.webcodegeeks.com\/author\/piyas-de\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"CouchDB: Basics and Operations - Web Code Geeks - 2026","description":"This article is part of our Academy Course titled CouchDB \u2013 Database for the Web. This is a hands-on course on CouchDB. You will learn how to install and","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.webcodegeeks.com\/web-development\/couchdb-basics-and-operations\/","og_locale":"en_US","og_type":"article","og_title":"CouchDB: Basics and Operations - Web Code Geeks - 2026","og_description":"This article is part of our Academy Course titled CouchDB \u2013 Database for the Web. This is a hands-on course on CouchDB. You will learn how to install and","og_url":"https:\/\/www.webcodegeeks.com\/web-development\/couchdb-basics-and-operations\/","og_site_name":"Web Code Geeks","article_publisher":"https:\/\/www.facebook.com\/webcodegeeks","article_author":"http:\/\/www.facebook.com\/phlocblogger","article_published_time":"2015-09-28T18:11:24+00:00","article_modified_time":"2018-01-05T14:53:10+00:00","og_image":[{"width":150,"height":150,"url":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2015\/09\/couchdb-logo-.jpg","type":"image\/jpeg"}],"author":"Piyas De","twitter_card":"summary_large_image","twitter_creator":"@https:\/\/twitter.com\/phloxblog","twitter_site":"@webcodegeeks","twitter_misc":{"Written by":"Piyas De","Est. reading time":"40 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.webcodegeeks.com\/web-development\/couchdb-basics-and-operations\/#article","isPartOf":{"@id":"https:\/\/www.webcodegeeks.com\/web-development\/couchdb-basics-and-operations\/"},"author":{"name":"Piyas De","@id":"https:\/\/www.webcodegeeks.com\/#\/schema\/person\/7aab6e040a06f0dfe0d60c27768aa424"},"headline":"CouchDB: Basics and Operations","datePublished":"2015-09-28T18:11:24+00:00","dateModified":"2018-01-05T14:53:10+00:00","mainEntityOfPage":{"@id":"https:\/\/www.webcodegeeks.com\/web-development\/couchdb-basics-and-operations\/"},"wordCount":6553,"commentCount":0,"publisher":{"@id":"https:\/\/www.webcodegeeks.com\/#organization"},"image":{"@id":"https:\/\/www.webcodegeeks.com\/web-development\/couchdb-basics-and-operations\/#primaryimage"},"thumbnailUrl":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2015\/09\/couchdb-logo-.jpg","keywords":["Databases"],"articleSection":["Web Dev"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.webcodegeeks.com\/web-development\/couchdb-basics-and-operations\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.webcodegeeks.com\/web-development\/couchdb-basics-and-operations\/","url":"https:\/\/www.webcodegeeks.com\/web-development\/couchdb-basics-and-operations\/","name":"CouchDB: Basics and Operations - Web Code Geeks - 2026","isPartOf":{"@id":"https:\/\/www.webcodegeeks.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.webcodegeeks.com\/web-development\/couchdb-basics-and-operations\/#primaryimage"},"image":{"@id":"https:\/\/www.webcodegeeks.com\/web-development\/couchdb-basics-and-operations\/#primaryimage"},"thumbnailUrl":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2015\/09\/couchdb-logo-.jpg","datePublished":"2015-09-28T18:11:24+00:00","dateModified":"2018-01-05T14:53:10+00:00","description":"This article is part of our Academy Course titled CouchDB \u2013 Database for the Web. This is a hands-on course on CouchDB. You will learn how to install and","breadcrumb":{"@id":"https:\/\/www.webcodegeeks.com\/web-development\/couchdb-basics-and-operations\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.webcodegeeks.com\/web-development\/couchdb-basics-and-operations\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.webcodegeeks.com\/web-development\/couchdb-basics-and-operations\/#primaryimage","url":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2015\/09\/couchdb-logo-.jpg","contentUrl":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2015\/09\/couchdb-logo-.jpg","width":150,"height":150},{"@type":"BreadcrumbList","@id":"https:\/\/www.webcodegeeks.com\/web-development\/couchdb-basics-and-operations\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.webcodegeeks.com\/"},{"@type":"ListItem","position":2,"name":"Web Dev","item":"https:\/\/www.webcodegeeks.com\/category\/web-development\/"},{"@type":"ListItem","position":3,"name":"CouchDB: Basics and Operations"}]},{"@type":"WebSite","@id":"https:\/\/www.webcodegeeks.com\/#website","url":"https:\/\/www.webcodegeeks.com\/","name":"Web Code Geeks","description":"Web Developers Resource Center","publisher":{"@id":"https:\/\/www.webcodegeeks.com\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.webcodegeeks.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.webcodegeeks.com\/#organization","name":"Exelixis Media P.C.","url":"https:\/\/www.webcodegeeks.com\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.webcodegeeks.com\/#\/schema\/logo\/image\/","url":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","contentUrl":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","width":864,"height":246,"caption":"Exelixis Media P.C."},"image":{"@id":"https:\/\/www.webcodegeeks.com\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/webcodegeeks","https:\/\/x.com\/webcodegeeks"]},{"@type":"Person","@id":"https:\/\/www.webcodegeeks.com\/#\/schema\/person\/7aab6e040a06f0dfe0d60c27768aa424","name":"Piyas De","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.webcodegeeks.com\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/eadd6728b7b5be23f0d6585da1a953926e49c6f2369703d6cb4f1147d4dd2203?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/eadd6728b7b5be23f0d6585da1a953926e49c6f2369703d6cb4f1147d4dd2203?s=96&d=mm&r=g","caption":"Piyas De"},"description":"Piyas is Sun Microsystems certified Enterprise Architect with 10+ years of professional IT experience in various areas such as Architecture Definition, Define Enterprise Application, Client-server\/e-business solutions.Currently he is engaged in providing solutions for digital asset management in media companies.He is also founder and main author of \"Technical Blogs (Blog about small technical Know hows)\"","sameAs":["http:\/\/www.phloxblog.in","http:\/\/www.facebook.com\/phlocblogger","http:\/\/in.linkedin.com\/in\/piyasde","https:\/\/x.com\/https:\/\/twitter.com\/phloxblog"],"url":"https:\/\/www.webcodegeeks.com\/author\/piyas-de\/"}]}},"_links":{"self":[{"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/posts\/7470","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/users\/18"}],"replies":[{"embeddable":true,"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/comments?post=7470"}],"version-history":[{"count":0,"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/posts\/7470\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/media\/7450"}],"wp:attachment":[{"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/media?parent=7470"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/categories?post=7470"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/tags?post=7470"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}