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