Skip to main content

This is my blog, more about me at marianoguerra.github.io

🦋 @marianoguerra.org 🐘 @marianoguerra@hachyderm.io 🐦 @warianoguerra

[EN] CouchApp V: filter documents by tag ordered by timestamp

you now have documents and to be in this century you decide to add tags to some elements so you can filter and categorize (say folksonomy and you will sound really hip!)


now, how do I filter the documents by tag?


if I can do that, how do I filter by tag and order by date?


now that we are at it, wouldn't be nice to have a filter by tag *and* date?


we will solve all this requirements with a simple view


first we create the view


couchapp generate view by-tag

this creates a view in the views called by-tags, this is a directory that contains two files, map.js and reduce.js


in this case we will only use the map.js file, so remove the reduce.js file


cd views/by-tag
rm reduce.js

now edit the map.js file to look like this


function(doc) {
if (doc.tags) {
doc.tags.forEach(function (element, index) {
emit([element, doc.created], doc);
});
}
}

here for each document in the database we check if the document has the tags attribute and if it has the attribute, for each tag we emit a document that contains as key an array with the tag and timestamp when the document was created and as value the document itself


now we push our changes to couchdb


couchapp push

to test that this works, create some documents with a field called tags that contains a list of strings and a field called created that contain the timestamp when the item was created


if I put this URL http://localhost:5984/datos/_design/datos/_view/by-tag/ in my browser I get something like this


{"total_rows":8,"offset":0,"rows":[
{"id":"d6de7e9a63039dc1af500a40af0014d7","key":["bar",1288644825761],"value":{"_id":"d6de7e9a63039dc1af500a40af0014d7","_rev":"1-eab86fbc2b4c24f31e1d60dfdd762793","author":"wariano", "created":1288644825761, "tags":["test","foo","bar"], ...}},
...
]}

this means the view worked, now to filter by tag the URL will get weird


we will use filters in the view to filter only for a specific tag


http://localhost:5984/datos/_design/datos/_view/by-tag?descending=false&startkey=["test", 0]&endkey=["test", 9999999999999]


with this request we say that we want to get the result of the view called by-tag, filtering starting with the key ["test", 0] and ending with the key ["test", 9999999999999]. This means that we only want the documents with the key "test" and we want all the timestamps (that's why the huge number in the endkey


if we want to sort the tags in descending order we should switch the start and endkey like this: http://localhost:5984/datos/_design/datos/_view/by-tag?descending=true&startkey=["test", 9999999999999]&endkey=["test", 0]


we can play with startkey and endkey to get a range of tags or one tag in a specific period, for example, "things tagged fun in the last 2 days"


the code to do the request to couchdb from javascript is the following


datos.getByTag = function (tag, descending, okCb, errorCb, startStamp, endStamp) {
var tmp;

startStamp = startStamp || 0;
endStamp = endStamp || 9999999999999;

if (descending) {
tmp = endStamp;
endStamp = startStamp;
startStamp = tmp;
}

$.couch.db(datos.db).view("datos/by-tag",
{"descending": descending, "startkey": [tag, startStamp], "endkey": [tag, endStamp],
"success": okCb, "error": errorCb});
};

with this you have a way to list documents by one or more fields, you can modify this a little to list by users, or by some other thing