user8691550
user8691550

Reputation: 39

Relay pagination using graphql-spqr, java and mongo

How can we create a paginated query using graphql spqr, java, mongo?

Below is how query would look like:

allUsers(first : int, last :int, after : String, before: String)

Upvotes: 0

Views: 1302

Answers (1)

kaqqao
kaqqao

Reputation: 15499

No Spring

If you want SPQR to automatically map the result as a Relay page, make sure you return a Page<> from your method. So something like:

public Page<User> allUsers(int first, int last, String after, String before) {
    List<User> users = queryMongo(...); //however you query Mongo
    return translateListToPage(users); //get a Page instance somehow, see below
}

I don't know if you can do real cursor-based pagination in Mongo (where you give it the last seen cursor and ask for the next batch of items), but if not you can always translate it to simple offset-based pagination or use a value of any field you can sort on as the cursor.

See my answer here for an idea how to implement these approaches. It describes a solution meant for a relational DB but the logic is the same. E.g. you use cursor.skip and cursor.limit instead of SQL's LIMIT and OFFSET.

In short, you can do something like:

public Page<User> allUsers(int first, String after) {
    //Treat 'after' as the offset to skip to
    int skip = Integer.valueOf(after);

    //Query Mongo (this is Mongo shell, do whatever you normally do in Java instead)
    List<User> users = db.users.find().skip(skip).limit(first);

    //Translate to Page
    Page<User> userPage = PageFactory.createOffsetBasedPage(users, totalUserCount, skip);

    return userPage;
}

There's many more ways to create a Page instance, including creating your own implementation of that interface.

Another way is something like:

public Page<User> allUsers(int first, String after) {
    //This time 'after' is the last seen ID
    List<User> users = db.students.find({'_id': {'$gt': after}}).limit(first);

    //Translate to Page somehow again (you have to somehow know if there's the next/previous page)
    Page<User> userPage = PageFactory.createPage(users, (user, ix) -> () -> user.getId(), hasNextPage, hasPreviousPage);

    return userPage;
}

Spring Data

If you're using Spring Data, you can return org.springframework.data.domain.Page (or Slice) and configure SPQR to map that as a Relay page. This feature will be supported out-of-the-box in the next release of SPQR Spring Boot Starter.

Upvotes: 1

Related Questions