Ir al contenido principal

Hi, I'm Mariano Guerra, below is my blog, if you want to learn more about me and what I do check a summary here: marianoguerra.github.io or find me on twitter @warianoguerra or Mastodon @marianoguerra@hachyderm.io

CouchApp V: filtrar documentos por tag ordenados por fecha

ahora tenemos documentos y para pertenecer a este siglo decidiste agregar tags a algunos elementos para poder filtrarlos y categorizarlos (decí folksonomia y vas a sonar mucho mas hip!)

ahora, como filtro documentos por tag?

si puedo hacer eso, como filtro por tag y ordeno por fecha?

ya que estamos, no seria lindo poder filtrar por tag *y* por fecha?

vamos a resolver todos estos requerimientos con una simple vista

primero creamos la vista

couchapp generate view by-tag

esto crea una vista en el directorio views llamado by-tag, este es un directorio que contiene dos archivos, map.js y reduce.js

en este caso vamos a usar solo map.js asi que borra reduce.js

cd views/by-tag
rm reduce.js

ahora edita map.js para que se vea como esto

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

por cada documento en la base de datos, vemos si tiene el atributo tags, si lo tiene, por cada tag en tags emitimos un documento cuya llave es un array con el tag y la fecha y cuyo valor es el documento en si.

ahora empujamos los cambios a couchdb

couchapp push

para probar que funciona, crea algunos documentos con el un campo llamado tags que contenga un array de strings y otro campo llamado created que contenga el timestamp en el que el documento fue creado

si pongo esta URL http://localhost:5984/datos/_design/datos/_view/by-tag/ en mi navegador, obtengo algo así:

{"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"], ...}},
...
]}

esto significa que la vista funciono, ahora para filtrar por tag la URL se va a poner un poco rara

vamos a usar filtros en la vista para filtrar solo los documentos con un tag especifico

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

con este request decimos que queremos los resultados de la vista llamada by-tag, filtrando los documentos empezando con la llave ["test", 0] y terminando con la llave ["test", 9999999999999]. Esto significa que solo queremos los documentos con la llave "test" y que queremos todos los timestamps (por eso el numero enorme en endkey)

si queremos ordenar los tags en orden descendente deberíamos cambiar el orden de starkey y endkey: http://localhost:5984/datos/_design/datos/_view/by-tag?descending=true&startkey=["test", 9999999999999]&endkey=["test", 0]

podemos jugar con startkey y endkey para obtener rangos de tags o un tag en un periodo de tiempo especifico, por ejemplo: "cosas taggeadas con fun en los últimos dos días"

el código para hacer el request a couchdb desde javascript es el siguiente

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});
};

con esto tenes una forma de listar documentos por uno o mas campos, podes modificar este ejemplo un poco para listar por usuario o por otras cosas