Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Join/sum with CouchDB

Using CouchDB, I currently have a document which represents an idea, you can rate this idea. Every idea is one document and every rating is a different document. I am doing this like this to avoid concurrent access problems when people are rating an idea.

My documents look like that (I have simplified them):

An idea:

{
 "_id": "idea1",
 "title": "A great idea"
}

Ratings:

{
 "_id": "rating1",
 "rating": 1,
 "author": "author1"
}

{
 "_id": "rating2",
 "rating": 1,
 "author": "author2"
}

I currently use a reduce function to return me the idea id and his/her rating (a simple sum of the ratings):

Map:

function(doc) {
  if (doc.type == "rating")
    emit(doc.idea_id, doc.rating);    
}

Reduce:

function(keys, values, rereduce) {
  return sum(values);
}

My question is: how could I "join" the "idea" document with the reduce result which represent the rating for the idea?

like image 803
e-Jah Avatar asked Feb 28 '23 21:02

e-Jah


2 Answers

Map:

function(doc) {
    switch (doc.type) {
        case "idea":   emit(doc._id,     ["idea",  doc]);         break;
        case "rating": emit(doc.idea_id, ["rating", doc.rating]); break;
    }
}

Reduce:

function(keys, values, rereduce) {
    var i, l, ret = {idea:null, rating:0};

    for (i = 0, l = values.length; i < l; ++i) {
        switch (values[i][0]) {
            case "idea":   ret.idea = values[i][1];    break;
            case "rating": ret.rating += values[i][1]; break;
        }
    }

    return ret;
}

Another option would be to use view collation to do the trick.

like image 155
Jakub Kulhan Avatar answered Mar 15 '23 20:03

Jakub Kulhan


First off, please don't create your own _id, let CouchDB create a uuid for you. It's much better, I promise you :)

The short answer is, you can't get the idea document with anything other than an additional query. Although the query is quite fast since you have the _id in your vote document.

If you wanted to return the the full documents for all of the votes, in order to grab comments or something, you could definitely do that. Just run the view query with ?include_docs=true

like image 32
mikeal Avatar answered Mar 15 '23 21:03

mikeal