Last Updated: February 25, 2016
·
10.54K
· yamill

Including relational data in a query (Parse.com)

Hey guys,

This is my first post here on coderwall. I wanted to go over including relational data in a query for the awesome service provided by Parse.com. Assuming you already setup your site with Parse, you will also need to include underscore.js.

So let's get started, shall we?

We have a Post object. Inside this Post object we have two relations (comments, likes).

Now, Parse suggests that your Posts should be loaded and the relational data should be loaded asynchronously to your view. But what if we want to load all of this data in one shot to our view? Personally, I think it's cleaner when all the data is loaded. This may take a a bit longer to load all of our objects, but as long as we have control over the limit of our data we should be ok.

Here's the code.

var Post = Parse.Object.extend("Post"); 
var query = new Parse.Query(Post);
query.limit(5);
query.descending("createdAt");

query.find().then(function(posts){
    var cb = _.after(posts.length, function(){
        //our callback data
    });
    _.each(posts, function(post){
        //grab relations
        var likes = post.relation("likes");
        var comments = post.relation("comments");

        likes.query().find().then(function(likes){
            comments.query().find().then(function(comments){
                cb();
            });
        });
    });
});

Now let's break it down:

We first start off by calling our Post object, creating our query, limiting our query to 5 posts, and sorting them by the date created (newest, to oldest).

var Post = Parse.Object.extend("Post"); 
var query = new Parse.Query(Post);
query.limit(5);
query.descending("createdAt");

We then run our query like so. The "posts" inside the parentheses of the function is so we can reference it inside our function later on using a loop to retrieve each post. Think of the "posts" like results.

query.find().then(function(posts){
});

Now to fetch each post inside our query. We use underscore.js to run our loop using the _.each function. Inside our _.each function we need to tell it grab the relational data from our query. We want to grab likes, and comments. We apply variables to each relation so we can query them. After we query them, we use Parse's Promises so once one query is completed, it will run the next one. After all the queries are loaded we have a callback function cb(); that then references to our callback function.

_.each(posts, function(post){
    //grab relations
    var likes = post.relation("likes");
    var comments = post.relation("comments");

    likes.query().find().then(function(likes){
        comments.query().find().then(function(comments){
            cb();
        });
    });
});

Our callback function lives inside the query. This callback function is also part of underscore.js. What it basically does is that uses the length of our posts, once it's received the length of our posts (5 callbacks in our case) it will run the function. This is where our final data will live.

var cb = _.after(posts.length, function(){
    //our callback data
});

So for example, lets say we wanted to pass the post data in our callback function. Lets create an array. We can call this data. You can put this at the very top of your code.

var data = new Array();

Right before our cb(); function we can push to our data the title, and body of our post.

data.push({ title: post.get('title'), body: post.get('body') });

Now we can return that data in our callback like so.

return data;

Here's what our final code should look like.

var data = new Array();
var Post = Parse.Object.extend("Post"); 
var query = new Parse.Query(Post);
query.limit(5);
query.descending("createdAt");

query.find().then(function(posts){
    var cb = _.after(posts.length, function(){
        return data;
    });
    _.each(posts, function(post){
        //grab relations
        var likes = post.relation("likes");
        var comments = post.relation("comments");

        likes.query().find().then(function(likes){
            comments.query().find().then(function(comments){
                data.push({title: post.get('title'), body: post.get('body') });
                cb();
            });
        });
    });
});

Hopefully this pro tip could bring to insight. If you have questions, or a better method of doing this, don't hesitate to leave your 2 cents!

3 Responses
Add your response

Thanks for the write up. So where about is the comment / like data stored as it doesnt look like you are using it anywhere.

Cheers

over 1 year ago ·

When i use ".after" function then parse give me error that ".after is undefined function".

really it is for parse? then help me
i want post table relations data in loop.

over 1 year ago ·

Hi there.
I ran across the very same problem on a recent project of mine. I used each instead to iterate over the collection and fetch every element of the relation. If the callback function returns a promise, each will not move onto the next element of the list, until the promise is fulfilled. https://parse.com/docs/js/api/classes/Parse.Query.html#methods_each. With this I was sure that I could get to every element of the collection. This is just an alternative and didn't need to use underscore. You can see the snippet here: https://gist.github.com/orangeeli/5995edf466c3de650319.

Great write up. Cheers.

over 1 year ago ·