0

In our CouchDB document database, we have documents with different "status" property values like this:

doc1: {status: "available"},
doc2: {status: "reserved"},
doc3: {status: "available"},
doc4: {status: "sold"},
doc5: {status: "available"},
doc6: {status: "destroyed"},
doc7: {status: "sold"}
[...]

Now, I would like to write a map-reduce function that returns all distinct status values that exist over all documents: ["available", "reserved", "sold", "destroyed"].

My approach was to begin writing a map function that returns only the "status" property of each document:

function (doc) {
  if(doc.status) {
    emit(doc._id, doc.status);
  }
}

And now, I would like to compare all map rows to each other such that no status duplicates will be returned.

The official CouchDB documentation seems to be very detailed and technical, but cannot really be projected to our use case, which does not have any nested structures like in blog posts but simply "flat objects" with a "status" property. Besides, our backend uses PouchDB as an adapter to connect to our remote CouchDB.

I discovered that when executing the reduce function below (which I implemented myself trying to understand what happens under the hood), some strange result will be returned.

function(keys, values, rereduce) {
  var array = [];

  if(rereduce) {
    return values;
  } else {
    if(array.indexOf(values[0]) === -1) {
      array.push(values[0]);
    }
  }

  return array;
}

Result:

{
  "rows": [
    {
      "key": null,
      "value": "[reduce] [status] available,available,[status] sold,unknown,[status] available,[status] available,[status] available,reserved,available,[status] reserved,available,[status] available,[status] sold,reserved,[status] sold,sold,[status] available,available,[status] reserved,[status] reserved,[status] available,[status] reserved,available"
    }
  ]
}

The reduce step seems to be executed exactly once, while the status loops sometimes have only a single value, then two or three values, without a recognizable logic or pattern.

Could somebody please explain to me the following:

  1. How to retrieve an array with all distinct status values
  2. What is the logic (or workflow) of the reduce function of CouchDB? Why do status rows have an arbitrary number of status values?
SparkFountain
  • 2,110
  • 15
  • 35

1 Answers1

1

Thanks to @chrisinmtown's comment I was able to implement the distinct retrieval of status values using the following functions:

function map(doc) {
  if(doc.status) {
    emit(doc.status, null);
  }
}
function reduce(key, values) {
  return null;
}

It is important to send the query parameter group = true as well, otherwise the result will be empty:

// PouchDB request
return this.database.query('general/all-status', { group: true }).pipe(
  map((response: PouchDB.Query.Response<any>) => response.rows.map((row: any) => row.key))
);

See also the official PouchDB documentation for further information how to use views and queries.

SparkFountain
  • 2,110
  • 15
  • 35
  • Cool. Please show how you send the query parameter group = true, that will help the next person also. – chrisinmtown Aug 13 '19 at 12:34
  • So, uh, are you using *Couch* or *Pouch* database? – chrisinmtown Aug 14 '19 at 12:21
  • I use a CouchDB instance as the remote database, but I also use PouchDB as a local adapter to connect to the remote DB from the NestJS backend. Thus, the request syntax is PouchDB conform while the design documents and view functions are stored in the remote CouchDB. – SparkFountain Aug 14 '19 at 12:48