Sorting GraphQL results

Problem

You want to sort results by a particular field in a GraphQL query.

Solution

You can sort GraphQL query results using an index and a user-defined function.

The following example uses the following components:

The GraphQL schema schema.gql looks like this:

graphqlCopied!
type Posts {
  title: String!
  content: String!
}

type Query {
  allPostsSortedByTitle: [Posts!]! @resolver(name: "sort_by_title", paginated: true)
}

When you import the above schema, the GraphQL API automatically creates a collection named Posts and a UDF named sort_by_title.

For more information about importing GraphQL schemas, see the GraphQL quick start.

We need an index to sort our documents:

Copied!
({
  "name": "all_posts_sorted_by_title",
  "source": ("Posts"),
  "values": [
    { "field": ["data", "title"] },
    { "field": [ "ref" ] }
  ],
})
{
  ref: ("all_posts_sorted_by_title"),
  ts: 1635289589810000,
  active: true,
  serialized: true,
  name: 'all_posts_sorted_by_title',
  source: ("Posts"),
  values: [ { field: [ 'data', 'title' ] }, { field: [ 'ref' ] } ],
  partitions: 8
}
Query metrics:
  •    bytesIn:   174

  •   bytesOut:   339

  • computeOps:     1

  •    readOps:     0

  •   writeOps:     1

  •  readBytes: 1,257

  • writeBytes:   473

  •  queryTime:  54ms

  •    retries:     0

We need some documents to sort. We can do this in either FQL or GraphQL. In FQL, the document creation command looks like this:

Copied!
(
  [
    { title: 'my second post', content: 'more placeholder content' },
    { title: 'my first post', content: 'placeholder content' },
    { title: 'my third post', content: 'even more placeholder content' },
  ],
  (
    'doc',
    (
      ('Posts'),
      { data: ('doc') },
    )
  )
)
[
  {
    ref: (("Posts"), "305856982752952832"),
    ts: 1627946798960000,
    data: { title: 'my second post', content: 'more placeholder content' }
  },
  {
    ref: (("Posts"), "305856982752953856"),
    ts: 1627946798960000,
    data: { title: 'my first post', content: 'placeholder content' }
  },
  {
    ref: (("Posts"), "305856982752954880"),
    ts: 1627946798960000,
    data: {
      title: 'my third post',
      content: 'even more placeholder content'
    }
  }
]
Query metrics:
  •    bytesIn:   346

  •   bytesOut:   666

  • computeOps:     1

  •    readOps:     0

  •   writeOps:     3

  •  readBytes:     0

  • writeBytes: 1,253

  •  queryTime:  43ms

  •    retries:     0

Or to create the documents with GraphQL, use the following mutation:

graphqlCopied!
mutation {
  post2: createPosts( data:{
  	title: "my second post"
    content: "more placeholder content"
  }) {
    _id
  },
  post1: createPosts( data:{
  	title: "my first post"
    content: "placeholder content"
  }) {
    _id
  },
  post3: createPosts( data:{
  	title: "my third post"
    content: "even more placeholder content"
  }) {
    _id
  }
}

Next, update the stub function sort_by_title:

Copied!
(
  ("sort_by_title"),
  {
    body: (
      (
        ["size", "after", "before"],
        (
          {
            match: (("all_posts_sorted_by_title")),
            page: (
              (("before"), null),
              (
                (("after"), null),
                (
                  ("match"),
                  { size: ("size") }
                ),
                (
                  ("match"),
                  { size: ("size"), after: ("after") }
                )
              ),
              (
                ("match"),
                { size: ("size"), before: ("before") }
              ),
            )
          },
          (
            ("page"),
            (
              "values",
              ((1, ("values")))
            )
          )
        )
      )
    )
  }
)
{
  ref: ("sort_by_title"),
  ts: 1635289852000000,
  name: 'sort_by_title',
  body: ((["size", "after", "before"], ({match: (("all_posts_sorted_by_title")), page: ((("before"), null), ((("after"), null), (("match"), {size: ("size")}), (("match"), {after: ("after"), size: ("size")})), (("match"), {before: ("before"), size: ("size")}))}, (("page"), ("values", ((1, ("values")))))))),
  data: { gql: 'not included for brevity' }
}
Query metrics:
  •    bytesIn:  637

  •   bytesOut:  771

  • computeOps:    1

  •    readOps:    0

  •   writeOps:    1

  •  readBytes:  274

  • writeBytes:  686

  •  queryTime: 23ms

  •    retries:    0

Now you have a function which gets results from the all_posts_sorted_by_title index and arranges them in alphabetical order.

The following GraphQL query uses the allPostsSortedByTitle query specified in the schema:

graphqlCopied!
query FindAllPosts {
  allPostsSortedByTitle {
    data {
      title
      content
    }
  }
}

The above query generates the following results, in alphabetical order by title:

{
  "data": {
    "allPostsSortedByTitle": {
      "data": [
        {
          "title": "my first post",
          "content": "placeholder content"
        },
        {
          "title": "my second post",
          "content": "more placeholder content"
        },
        {
          "title": "my third post",
          "content": "even more placeholder content"
        }
      ]
    }
  }
}

Is this article helpful? 

Tell Fauna how the article can be improved:
Visit Fauna's forums or email docs@fauna.com

Thank you for your feedback!