How to paginate an async has many relationship?


#1

When retrieving a record through the RESTAdapter, like so:

this.store.find('post', 1).then(function(post) {
    // async, get comments of this post.
    post.get("comments").then(function(comments) {
        // .. we got the comments.
    });
});

Of cource, the server is not returning all comments for this post. So how would I get the comments on the next page (our API uses the page query parameter for this).

I tried something like this, but this does not work:

// get the comments on the second page.
post.get("comments", { page: 2 }).then(function(comments) {
    // .. we got the comments.
});

How would this be done in Ember Data in a nice way?


#2

tl;dr;

Absent a native Ember Data way to do this you could just add the ID of the post object to your query for comments.

this.get('store').find('comment', { page: 2, postId: this.get('post.id') })

And those comment objects will find their way into the store.

The long version

Is your API returning a collection of IDs for the comments property on your post model? If so, Ember Data will automatically reach out to your API and retrieve the object at /comments/:id whenever it realizes it needs to resolve that object.

Obviously, depending on how many you try to resolve at any one time that’s X# of outstanding requests all hitting your API at once. So, within your code you could request a page at a time using DS.Adapter.findMany.

this.get('store').findMany('comment', [1, 2, 3, 4, 5]).then(...);

Which will then return the desired collection of comments in a single call (assuming your API can handle query strings in the format comment[]=1&comment[]=2&comment[]=3).

The array of IDs can be built from a slice of the post object’s collection of IDs for that relationship. However, this is where my understanding breaks down, since I don’t know of an API that can get you at the raw collection of IDs for a hasMany relationship…

Ideally, Ember Data would batch several calls to find for the same object type together that are requested in a single iteration of the run loop into a findMany call for you so you wouldn’t need to do explicit paging at the Controller level at all. It would ‘just work’ depending on how many you’re trying resolve in that run loop iteration. I’ve seen requests for intelligent Ember Data batching for run loop queues before, but it’s obviously a non-trivial thing to do.