What is a good pagination strategy for nested collections?


#1

The spec mentions:

A relationship object that represents a to-many relationship MAY also contain pagination links under the links member, as described below.

Assuming I have chosen page[limit] and page[offset] as parameters for pagination of my primary data, what would be a recommended approach for pagination of the nested collection?


#2

I suggest page[limit] and page[offset].

This is one of the many, many reasons which I constantly say unrelated resources should not ever be included as sub resources in the path. The answer is simple, your related collection should use the canonical URL for the resource related to it, as such all you need to provide is the pagination parameters for the related collection within the link. Paginating the two resources is only in conflict if you have to somehow provide query parameters to paginate them simultaneously, and I’m at a loss to come up with a reason a use case for this.

It is a big example, but look and see how unrelated comment-author and post are to each other.

 {
   "data": [
     {
       "type": "post",
       "id": "1",
       "attributes": {
         "title": "It's a title.",
         "relationships": {
           "comment-author": {
             "links": {
               "self": "http://example.com/articles/1/relationships/comment-author",
               "related": "http://example.com/comment?filter[article]=1&page[limit]=50&page[offset]=0"
             }
           },
           "author": {
             "links": {
               "self": "http://example.com/articles/1/relationships/author",
               "related": "http://example.com/people?filter[article]=1"
             },
             "data": {
               "type": "people",
               "id": "9"
             }
           }
         }
       },
       "links": {
         "self": "http://example.com/articles/1"
       }
     },
     {
       "type": "post",
       "id": "2",
       "attributes": {
         "title": "It's a title.2",
         "relationships": {
           "comment-author": {
             "links": {
               "self": "http://example.com/articles/2/relationships/comment-author",
               "related": "http://example.com/comment?filter[article]=2&page[limit]=50&page[offset]=0"
             }
           },
           "author": {
             "links": {
               "self": "http://example.com/articles/2/relationships/author",
               "related": "http://example.com/people?filter[article]=2"
             },
             "data": {
               "type": "people",
               "id": "9"
             }
           }
         }
       },
       "links": {
         "self": "http://example.com/articles/2/relationships/author"
       }
     }
   ],
   "included": [
     {
       "type": "people",
       "id": "9",
       "attributes": {
         "first-name": "Dan",
         "last-name": "Gebhardt",
         "twitter": "dgeb"
       },
      "links": {
        "self": "http://example.com/people/9"
      }
    }
  ],
  "links": {
    "self": "http://example.com/articles?filter[author]=9",
    "first": "http://example.com/articles?filter[author]=9",
    "next": "http://example.com/articles?filter[author]=9&page[limit]=50&page[offset]=1",
     "last": "http://example.com/articles?filter[author]=9&page[limit]=50&page[offset]=10"
  }
}

#3

I think the scenario which you identified as problematic is what was on my mind.

I imagine I have a post with 1000 comments. Not something I would like to deliver in a single batch when the user requests that post. But, given that they are relationships of the post, I would include resource identifiers for all of them.

Now when I request the first page of posts, I imagine that the response contains the first 50 posts and for each of those posts, the first 50 resource identifiers for comments.

I could imagine a user wanting to now retrieve the next page of 50 comments for a given post. But I can see now that this information could trivially be requested through the appropriate comments relationship endpoint for that post, instead of trying to think up some complicated parameter syntax.

Cheers :slight_smile:


#4

Good luck, I generally advocate keeping things like the interaction with the service as simple as possible, while still usable and intuitive.

One point of advice regarding the 1000 comments scenario, don’t include any data if that will bloat the message beyond your concept of a reasonable size and don’t truncate the list implicitly. Doing either would result in a worse experience for the consumer than requiring they dereference the related link to discover or interact with the resource collection. If you have a need to provide information to the caller, comment count for instance, send that back as part of the relationship link in a meta ‘count’ field.


#5

That is excellent advise. Thanks a lot