Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to manage cursors and sorting in Relay?

Tags:

relayjs

We have a graphql server (not written in javascript) serving a paginated list of objects. We're trying to conform to the relay specification, but we've hit an interesting case that could use clarification.

Specifically: are cursors allowed to depend on other inputs to the connection? Similar to https://github.com/graphql/graphql-relay-js/issues/20, our connection takes a sort_key argument that determines the sort order of the returned list. Depending on the specified sort order, the edge for an object may return different cursor values (since the server needs different information in each case to determine the next object). However, a careful reading of https://facebook.github.io/relay/docs/guides-mutations.html#range-add suggests this is not permitted; mutations that return a newly created edge must return a single cursor that can be universally applied to all possible lists in which that edge may appear? How does facebook solve this problem?

like image 694
Evan Avatar asked Jan 22 '16 13:01

Evan


1 Answers

I had the same problem. So, I decided to write a npm package to handle this issue.

You can use fast-relay-pagination npm package for sorting, backward and forward pagination and filter Mongoose model or MongoDB object.

This package improves graphql-relay lazy loading by using Mongoose or MongoDB find and limit. As you definitely know, graphql-relay's connectionFromArray fetchs all data and performs slicing on data, which is not efficient for large amount.


You can see an example in below:

...
import {
  fetchConnectionFromArray
} from 'fast-relay-pagination'
...
export default{
  type: orderConnection.connectionType,
  args: {
    ...connectionArgs,
    orderFieldName: {
      type: GraphQLString,
    },
    sortType: {
      type: GraphQLInt,
    },
  },
  resolve: needAdmin(async (_, args) => {
    let orderFieldName = args.orderFieldName || '_id'
    let sortType = args.sortType || -1
    let after = args.after
    let before = args.before
    let filter = args.filter
    let first = args.first
    let last = args.last
    return fetchConnectionFromArray({
      dataPromiseFunc: SampleModel.find.bind(SampleModel), // required
      filter, // optional (for using filter on model collection) - for example => {username: 'test'} 
      after, //optiona
      before, // optional
      first, //optional
      last, // optional
      orderFieldName, // optional
      sortType, // optional
    })
  }),
}
like image 120
Saeed Gharedaghi Avatar answered Sep 20 '22 21:09

Saeed Gharedaghi