GraphQL Queries
For each entity you define there will be two query fields - one for fetching a single record by a unique field and one for fetching a list of records.
For following entity:
import { SchemaDefinition as def } from "@contember/schema-definition";
export class Post {
title = def.stringColumn().notNull();
publishedAt = def.dateTimeColumn();
}
GraphQL schema will be similar to this (some types are omitted in the example for clarity):
query {
getPost(by: PostUniqueWhere!): Post
listPost(filter: PostWhere, orderBy: [PostOrderBy!], offset: Int, limit: Int): [Post]
}
input PostUniqueWhere {
id: UUID
}
input PostOrderBy {
id: OrderDirection
publishedAt: OrderDirection
}
input PostWhere {
id: UUIDCondition
publishedAt: DateTimeCondition
and: [PostWhere!]
or: [PostWhere!]
not: PostWhere
}
enum OrderDirection {
asc
desc
}
Fetching a single record
If you know a field, which uniquely identifies a record, you can fetch a single record using a "get" query. If you define an entity called Post
, there will be a field getPost
with a parameter by
.
query {
getPost(by: { id: "c4ae3a0f-d91b-42a8-ad3c-5ca6b9f407c2" }) {
title
publishedAt
}
}
The by
parameter allows to filter by any unique column (or columns in case of compound unique key). By default it is only id
, but you can specify them in model by .unique()
on the column or using @def.Unique(...)
class annotation.
Fetching a list of records
This kind of query offers more possibilities like filtering using complex conditions, ordering the result or paging using limit and offset.
query {
listPost(
filter: {
publishedAt: { lte: "2019-12-20" }
category: { name: { eq: "Graphql" } }
}
orderBy: [{ publishedAt: asc }]
limit: 10
) {
title
publishedAt
}
}
Filters
filter
argument allows you to apply a filter on the result. On columns you can use following conditions:
Comparison operators
GraphQL name | Description | Example | Supported columns |
---|---|---|---|
isNull | is (not) null | {isNull: true} or {isNull: false} | Everywhere |
eq | equal to | {eq: "value"} | Everywhere but JSON |
notEq | not equals to | {notEq: "value"} | Everywhere but JSON |
in | is in list | {in: ["A", "B"]} | Everywhere but JSON |
notIn | is not in list | {in: ["A", "B"]} | Everywhere but JSON |
lt | less than | {lt: 100} | Everywhere but JSON |
lte | less than or equals to | {lte: 100} | Everywhere but JSON |
gt | greater than | {gt: 100} | Everywhere but JSON |
gte | greater than or equals to | {gte: 100} | Everywhere but JSON |
contains | contains a string (case sensitive) | {contains: "contember"} | String only |
containsCI | contains a string (case insensitive) | {containsCI: "contember"} | String only |
startsWith | starts with a string (case sensitive) | {startsWith: "contember"} | String only |
startsWithCI | starts with a string (case insensitive) | {startsWithCI: "contember"} | String only |
endsWith | ends with a string (case sensitive) | {endsWith: "contember"} | String only |
endsWithCI | ends with a string (case insensitive) | {endsWithCI: "contember"} | String only |
Logic operators
GraphQL name | Example |
---|---|
and | {and: [{ gte: "2019-12-20" }, { lte: "2019-12-30" }]} |
or | {or: [{isNull: true}, {eq: "value"}]} |
not | {not: {eq: "value"}} |
Example: GraphQL type for String condition
input StringCondition {
and: [StringCondition!]
or: [StringCondition!]
not: StringCondition
null: Boolean
isNull: Boolean
eq: String
notEq: String
in: [String!]
notIn: [String!]
lt: String
lte: String
gt: String
gte: String
contains: String
startsWith: String
endsWith: String
containsCI: String
startsWithCI: String
endsWithCI: String
}
note
It is not possible to combine multiple fields in a single object. You have to wrap it using and
or or
fields.
Example: combining two operators using AND
query {
listPost(
filter: {
publishedAt: { and: [{ gte: "2019-12-20" }, { lte: "2019-12-30" }] }
}
) {
id
title
}
}
Example: filtering over relation
You can also filter over relations (both "has one" and "has many"), for example you want to only select posts written by "John Doe" and published with a "graphql" tag
query {
listPost(
filter: {
author: { name: { eq: "John Doe" } }
tag: { caption: { eq: "graphql" } }
}
) {
id
title
}
}
Sorting result
Result set can be sorted by setting an orderBy
argument. This argument can contain multiple sort fields and can also contain relations.
Example
query {
listPost(
orderBy: [
{ author: { name: asc } },
{ publishedAt: desc }
]
) {
id
title
}
}
Records pagination
There is an alternative to a list queries with a similar structure - a "paginate" queries. This query aims to be Relay compatible in the future.
In addition to fields for fetching a list of records, there is a pageInfo
object with totalCount
field. Using this value you can calculate total number of pages etc.
query {
paginatePost(
skip: 1
first: 2
filter: { author: { name: { eq: "John Doe" } } }
orderBy: [{ publishedAt: asc }]
) {
pageInfo {
totalCount
}
edges {
node {
id
title
author {
name
}
}
}
}
}
Syntax for filtering and sorting is the same you know from "list" query. Parameters for pagination (skip, first) follows Relay specification.
Cursor based pagination is not supported.
Nested objects
In a single query you can traverse across all the relations of given record.
query {
listPost {
id
title
category {
name
}
author {
name
}
}
}
On "has many" relations, you can also set a filter, orderBy and limit with an offset.
query {
listCategory {
id
title
posts(limit: 3, orderBy: [{ publishedAt: desc }]) {
title
}
}
}
Transactions
A transaction is NOT automatically started for queries. This results in a better performance, but it may cause an inconsistency in the result.
To enable transactions, wrap queries into a transaction
field.
query {
transaction {
listPost {
title
}
listAuthor {
name
}
}
}