For the couchapp I'm writing, I recently wanted to do a bulk delete operation with CouchDB, but found very little about it on the web. I don't know if my approach is the best way to go, but well, it works - if you know a better way, I'm happy to learn about it.
In the file jquery.couch.js that comes with CouchDB there are a couple of convenience methods to help you dealing with the database, documents and views. There is a method for deletion too (removeDoc), but it only can handle one document at a time. In the style of bulkSave, I added a bulkRemove method:
bulkRemove: function(docs, options){ docs.docs = $.each(docs.docs, function(i, doc){doc._deleted = true}); $.extend(options, {successStatus: 201}); ajax({ type: "POST", contentType: "application/json", dataType: "json", data: toJSON(docs), url: this.uri + "_bulk_docs" + encodeOptions(options) }, options, "The documents could not be deleted" ); },
In here I add the attribute "_deleted = true" to every document I want to delete, and then I do a bulk update with the documents. That's it.
This is one possible use case: In the delete action of my controller I first fetch an array with the post and its comments from the couch (how to do this see below), and then I call the bulkRemove action on that array.
couchapp.design.view('post_with_comments', { startkey: [params['id']], endkey: [params['id'], {}], success: function(json) { if (json.rows.length > 0) { var post_and_comments = json.rows.map(function(row) {return row.value}); couchapp.db.bulkRemove({docs: post_and_comments}, { success: function() { flash = {message: 'Post deleted.', type: 'notice'} redirect('#/outlines', flash); }, error: function(response_code, msg) { flash = {message: 'Error deleting post: ' + msg, type: 'error'}; } }); } } });
Note that the "flash" object I'm using is my own Sammy.js implementation of a Rails-like flash to show a message after a redirect. Maybe I'll share that in another blog post.
As a bonus, this is the view I'm using to retrieve a post and its comments in one request. I'm following the pattern Christopher Lenz is recommending in his article on CouchDB Joins.
function(doc) { if (doc.type == "Post") { emit([doc._id, 0], doc); } else if (doc.type == "Comment") { emit([doc.post_id, 1, Date.parse(doc.created_at)], doc); } }
When you call this view with
startkey: [params['id']], endkey: [params['id'], {}]
you get an array with the post as the first element, and then all the comments that have the post's ID as post_id.
This can of course also be used for things other than deleting: to show all the comments for a post, I get the array's first element and extract the title and content. Then I remove it from the array with
json.rows.splice(0,1);
You now have an array with only the post's comments and you can display them somehow.
Trackbacks
Use the following link to trackback from your own site:
http://lenaherrmann.net/trackbacks?article_id=8
about 1 hour later:
Cool stuffs! Can you open an issue on the CouchDB bugtracker so we can add the method?
https://issues.apache.org/jira/browse/COUCHDB
Cheers
Jan
12 days later:
The issue is here: https://issues.apache.org/jira/browse/COUCHDB-612