Get total count in pagination query

Schema:

type Query
  queryBlogPostsIndex(first: Int!, offset: Int!, keyword: String!): [BlogPost] @custom(dql: """
    query q($first: int, $offset: int, $keyword: string) {
      queryBlogPostsIndex(func: type(BlogPost), first: $first, offset: $offset) @filter(regexp(BlogPost.title, $keyword)){
        id: uid
        isPublished: BlogPost.isPublished
        title: BlogPost.title
        slug: BlogPost.slug
      }
    }
  """)

  queryBlogPostsIndexMetadata(keyword: String!): Metadata @custom(dql: """
    query q($keyword: string) {
      var(func: type(BlogPost)) @filter(regexp(BlogPost.title, $keyword)) {
        a as count(uid)
      }

      queryBlogPostsIndexMetadata() @normalize {
        total_count : sum(val(a))
      }
    }
   """)
}

$lib/graphql/queries/blog.graphql:

query queryBlogPostsIndex($first: Int!, $offset: Int!, $keyword: String!) {
  queryBlogPostsIndex(first: $first, offset: $offset, keyword: $keyword) {
    title
    slug
  }
  queryBlogPostsIndexMetadata(keyword: $keyword) {
    total_count
  }
}

Frontend logic

  import { queryBlogPostsIndex } from "$lib/graphql/queries/blog.graphql";

          data: (opts) => {
          return new Promise((resolve, reject) => {
            let variables = {
              keyword: "//i", // important default value!!
              first: 10,
              offset: 0,
              ...opts.body
            }

            graphQLClient.request(queryBlogPostsIndex, variables)
              .then((res) => {
                resolve({
                  data: res.queryBlogPostsIndex.map(post => {
                    return [post.title, post.slug]
                  }),
                  total: res.queryBlogPostsIndexMetadata.total_count
                })
              })
              .catch((error) => {
                reject(error)
              })
          })
        }

This code by returns two datasets, one for the given page (based on first and offset) and one for the ‘metadata’ which has the given total for the everything matching the query. By default it’ll query for all blog posts (func: type(BlogPost)), and if a keyword value is provided, it’ll filter that query for the keyword (requires a regexp index on the relevant predicate).

Aside: The frontend logic is designed to work with gridjs: parser for Graphql or Json data · Issue #44 · grid-js/gridjs · GitHub