CouchDB getting all posts from user in Node.js

1.6k Views Asked by At

I'll start off by saying I've done a lot of research but I'm still pretty lost.

I have a working version, but it's the most inefficient way you can do this I'm sure. I'm not super confident about knowing the best way to plan out a DB, I've become to dependent on ActiveRecord, clearly. Anyways, I'm simply trying to figure out these things:

  1. Find out the best way to plan the db (how I should separate documents)
  2. Find the most efficient to deal with relations
  3. Find good method to query from the server

Ok, so some things I've noticed: One, you can't pass I client variable into views so using a method like that won't work. Two, I think there might be away to get all posts and then check if the type is post and then return the matching documents, but that seems like a lot of data moving around.

Some code:

So I'm using Node.js, CouchDB, and nano as middleware.

Post Document:

{
"_id": "post-slug",
"title": "Post Slug",
"user": "film42",
"date": 1343451412,
"type": "post"
}

User Document:

{
"_id": "film42",
"email": "[email protected]",
"posts": [
   "post-slug",
   "another-post-slug"
],
"type": "user"
}

And here's how I currently fetch all posts (It's really bad!):

function buildUserPostArray(array, user, res, i) {
   db.get(user.posts[i], function(err, post_obj) {
       if(i < user.posts.length) {
           array.push(post_obj);
           buildUserPostArray(array, user, res, i+1);
       }
       else {
           console.log('Rendering view now.');
           res.render('user.jade', {
               user: user.user,
               posts: array
           });
       }
   });
}

app.get('/users/:id', function(req, res) {
    db.get(req.params.id, function(err, user_obj) {
       if(err) res.send('err1'); //bad id or server down

       array = [];
       buildUserPostArray(array, user_obj, res, 0);
    });
});

I was using views until I realized that I can't pass a variable and then I looked into lists but I got lost after reading many tutorials.

Thanks for the help!!

2

There are 2 best solutions below

0
On BEST ANSWER

You really want to use a view. Simply create the view on the post with the user as the key.

function(doc) {
    emit(doc.user, {title: doc.title, date: doc.date, id: doc._id});
}

Then you can simply query it:

GET /yourdb/_design/app/_view/by_user?key=film42

That will give you all of the view documents associated with that user.

1
On

Like Will Hartung said, you want a view however it should look a bit differently than how Will showed.

First of all make sure that the fields you want to emit exist. Keep in mind that null and 0 are falsy values in JavaScript so depending on your data structure you may have to check if fields are undefined explicitly.

Here is some code to show you what I mean.

function(doc) {
    if (doc.user && doc.title) { // This check is important
        emit(doc.user, {title: doc.title, date: doc.date});
    }
}

You don't have to emit the doc ID explicitly as that happens automatically anyway. Also make sure not to emit entire documents emit(doc.user, doc);. That is inefficient. In case you need the entire document just emit null as value and use the include_docs=true URL parameter.

So basically if you emit null as a value then you'd get the document like this.

GET /yourdb/_design/app/_view/by_user?key=film42&include_docs=true