delete() in reduce function ?

Hi all,

I am trying to use a map/reduce combination to be able to perform a partial bulk delete on a bucket.

Here is a sample of a document, :

"product-Walmart-NewYork-123": {
    sku: 123
    name: "Coffee machine"
    price: $1.23
    facility: "NewYork"
}

I want to delete all products available at the Walmart's New York facility. I don't know in advance all the skus of the products in this facility.

Solution 1 : delete in map

I can trick the system this way :

map = function (doc, meta) {
    if (meta.id.indexOf('product-Walmart-NewYork-') === 0) {
        delete(meta.id);
    }
}
reduce = null

But this forces me to create a "view" for each facility (since it seems we cannot pass parameters to views).

Solution 2 : delete in reduce

Thus here is what I tried :

map = function (doc, meta) {
    if (meta.id.indexOf('product-Walmart-') === 0) {
        emit(doc.facility, meta.id); // Emits products for all facilities
    }
}
reduce = function(key, values, rereduce){
    for (i=0; i < values.length; i++) {
       delete(values[i]);
    }
}

Using a startkey=["NewYork"] and endkey=["NewYork"], I understand can filter the output of the map function to only perform deletions on the values of the "NewYork" facility.

Unfortunately, it does not seem to work : the associated documents are not deleted...

Any ideas on this matter ?

Thanks in advance,

Antoine

1 Answer

« Back to question.

What do you mean, when you use delete? Javascript operator, which removes object's property?

I guess you mean you rather need to delete objects from the bucket after fetching the list using views. The map/reduce in Couchbase is not for batching some modifications of the database, it used to build the secondary index, i.e. you cannot modify anything neither from map, nor from reduce code.

The correct solution here will be:

1) build map function which returns facility as the key, and id as a value

function (doc, meta) {
  emit(doc.facility);
}

2) now just execute this view to fetch list of ID-s and pass them to delete function. For example for ruby will will look like this (assuming the view stored as _design/wallmart/_view/by_facility

require 'rubygems'
require 'couchbase'
 
conn = Couchbase.connect(bucket: "default", hostname: "localhost")
view = conn.design_docs["wallmart"]
           .by_facility(start_key: "NewYork", end_key: "NewYork\ufffd")
view.each do |doc|
  conn.delete(doc.id)
end

Note \ufffd is the largest valid codepoint in Unicode