CouchDB - Updating a Document
CouchDB - Managing Document Lifecycles
Section titled “CouchDB - Managing Document Lifecycles”In CouchDB, documents are not modified in place. Instead, updating a document means creating a new revision of it. This process is fundamental to CouchDB’s Multi-Version Concurrency Control (MVCC) model, which prevents data loss in distributed or highly concurrent environments.
The Core Concept: Revisions (_rev)
Section titled “The Core Concept: Revisions (_rev)”Every document in CouchDB has a _id (its unique identifier) and a _rev (its revision number). To update a document, you must provide the _rev of the version you are updating. If the _rev you provide matches the one currently in the database, your update is accepted, and a new revision is created with a new _rev. If it doesn’t match, CouchDB rejects the update with a 409 Conflict error. This mechanism ensures that you don’t accidentally overwrite changes made by another process.
Updating a Document with cURL
Section titled “Updating a Document with cURL”The cURL command-line tool is excellent for testing and direct API interaction. The workflow to update a document has two steps:
Step 1: Get the Current Document to find its _rev
Section titled “Step 1: Get the Current Document to find its _rev”Let’s assume we have a user profile in our profiles database with the id user123.
# Request$ curl -X GET http://127.0.0.1:5984/profiles/user123
# Response{ "_id": "user123", "_rev": "1-a954784578bca65545a1989467262913", "name": "Alice", "email": "alice@example.com", "status": "active"}Take note of the _rev value: 1-a954784578bca65545a1989467262913.
Step 2: Submit the Updated Document with the _rev
Section titled “Step 2: Submit the Updated Document with the _rev”Now, we’ll update the user’s status to inactive. We must include the entire document body along with the _rev we just fetched.
# Request$ curl -X PUT http://127.0.0.1:5984/profiles/user123 -d \'{ "_id": "user123", "_rev": "1-a954784578bca65545a1989467262913", "name": "Alice", "email": "alice@example.com", "status": "inactive"}'
# Response{ "ok": true, "id": "user123", "rev": "2-d7b1372551421f5286f7887720c1e879"}Success! The response shows "ok": true and provides the new revision number, which starts with 2-. If we wanted to update the document again, we would need to use this new _rev.
Programmatic Updates: Using Node.js and Axios
Section titled “Programmatic Updates: Using Node.js and Axios”In a real application, you’ll perform these operations programmatically. Here is a complete example using Node.js and the popular axios HTTP client. First, ensure you have axios installed: npm install axios.
const axios = require('axios');
const dbUrl = 'http://127.0.0.1:5984/profiles';const docId = 'user123';
async function updateUserStatus(newStatus) { try { // Step 1: Fetch the latest document to get the current _rev console.log(`Fetching document: ${docId}`); const getResponse = await axios.get(`${dbUrl}/${docId}`); const document = getResponse.data; console.log(`Current revision is: ${document._rev}`);
// Step 2: Modify the document and prepare the update payload const updatedDocument = { ...document, // Copy all existing fields status: newStatus, // Overwrite the status field updatedAt: new Date().toISOString() // Add a new field };
// The _rev is already in the document object, so we don't need to add it again.
// Step 3: PUT the updated document back to the database console.log(`Updating document with status: ${newStatus}`); const putResponse = await axios.put(`${dbUrl}/${docId}`, updatedDocument);
console.log('Update successful!'); console.log('New revision:', putResponse.data.rev); return putResponse.data;
} catch (error) { // Handle potential errors if (error.response) { console.error(`Error: ${error.response.status} - ${error.response.data.reason}`); if (error.response.status === 409) { console.error('Conflict: The document was updated by another process. Please retry the operation.'); } } else { console.error('An unexpected error occurred:', error.message); } return null; }}
// Run the update functionupdateUserStatus('suspended');Updating Documents using the Fauxton Web UI
Section titled “Updating Documents using the Fauxton Web UI”Fauxton is the modern, built-in web administration console for CouchDB. It provides a user-friendly way to manage documents. (Access it at http://127.0.0.1:5984/_utils/)
- Navigate to your database: From the main Fauxton dashboard, click on the ‘Databases’ icon on the left and then select your database (e.g.,
profiles) from the list. - Select the document: A list of documents in the database will appear. Click on the
_idof the document you wish to update (e.g.,user123). - Edit the document: The document’s content will be displayed as editable JSON in a text editor. You can directly modify the values of the fields. For example, change the
"status"value from"active"to"inactive". - Save the changes: Click the green ‘Save Document’ button. Fauxton automatically handles fetching the latest
_revand including it in the update request, making the process seamless and safe from conflicts.
Common Pitfalls & Best Practices
Section titled “Common Pitfalls & Best Practices”- Handling
409 Conflict: This is not an error; it’s a feature. Your application logic must be prepared to handle it. The correct strategy is to catch the 409, re-fetch the document to get the new_rev, and re-apply your changes before attempting thePUTrequest again. - Bulk Updates: If you need to update many documents at once, do not send one request per document. This is inefficient. Instead, use the
_bulk_docsendpoint to send a batch of updated documents in a single HTTP request for significantly better performance. - Never Hardcode
_rev: The revision of a document is dynamic. Never hardcode a_revvalue in your application code. Always fetch it just before you intend to perform an update.