📜 ⬆️ ⬇️

List functions in CouchDB

On Habré is often found a comment that the developers do not read the documentation to the end. I encountered this myself when I discovered the List functions in CouchDB.

The question seemed to me rather complicated and not very well explained in the documentation, I decided to share my research with a respected community.

List functions in CouchDB design documents are needed in order to be able to process the entire database with a single function. Those. This is a kind of Full Table Scan in relational databases.

Consider a design document from a really working CouchDB installation.
')
{ "_id": "_design/complete", "_rev": "2-45c7b0280b529d99b1d34f362e457860", "views": { "freq": { "map": "function(doc) { emit(doc.REQUEST, 1);}", "reduce": "function (key, values, rereduce){return sum(values);}" } }, "lists": { "basicJSON": "function(head, req) { start({headers :{'Content-Type' : 'text/plain;charset=utf-8'}}); send('{\"head\":'+toJSON(head)+', ');send('\"req\":'+toJSON(req)+', ');send('\"rows\":[');var row;var prev = null;while (row = getRow()){if (prev != null && prev.key == row.key) {} else {if (prev != null) { send(',');} send(toJSON({id: row.id, key: row.key}));} prev = row;} send(']}');}" } } 


CouchDB doesn’t like carriage transfers in functions, so all functions go in one line. For better readability, I will deploy the function basicJSON in lists:

 function (head, req) { start({ headers: { 'Content-Type': 'text/plain;charset=utf-8' } }); send('{\"head\":' + toJSON(head) + ', '); send('\"req\":' + toJSON(req) + ', '); send('\"rows\":['); var row; var prev = null; while (row = getRow()) { if (prev != null && prev.key == row.key) {} else { if (prev != null) { send(','); } send(toJSON({ id: row.id, key: row.key })); } prev = row; } send(']}'); 


What is interesting here?
The key element is the processing cycle:

  var row; ... while (row = getRow()) { ... send(','); ... send(toJSON({ id: row.id, key: row.key })); ... } 


Since we are working with HTTP when accessing CouchDB, the list function builds an http response. Those. essentially generates text in some kind of encoding. The send () function is responsible for this; It returns the text string to the server's http response. You can use the send (toJSON ()) construct; to return a textual representation of JSON objects.

getRow () gets the next entry in the database. Actually, on its basis a processing cycle is formed.

The start function is responsible for generating the http response header.

The given list-function is called like this:

http: // localhost: 5984 / requests-db / _design / complete / _list / basicJSON / freq? reduce = false

The name of the database, design-document, _list, the name of the function of the list, representation are indicated. Then come the presentation options. Parameters can be specified in the same way as when referring to any view.

Thus, using the list-functions, you can perform the necessary data processing, one that is not always available using Map / Reduce or will be very difficult on the client. Using conditions in a loop, you can filter out some of the records, or you can make several send () calls to one record, which will increase the number of records in the response.

As a result, http-text is constructed, which contains all records in the database that have passed through functional processing.

Yes, of course, this is not a very fast processing, but even in relational databases, full table scan is the slowest operation.

List functions are a very convenient and useful mechanism, which many do not read in the documentation. At least me.

Have a nice code!

Ps. There are show-functions in CouchDB, but about this some other time.

Source: https://habr.com/ru/post/144628/


All Articles