For the purposes of this section we will consider the default
module containing the following schema:
type Author {
property name -> str;
}
type Book {
# to make the examples simpler only the title is
# a required property
required property title -> str;
property synopsis -> str;
link author -> Author;
property isbn -> str {
constraint max_len_value(10);
}
}
From the schema above EdgeDB will expose to GraphQL:
Object types: Author
and Book
scalars String
and ID
In addition to this the Query
will have 2 fields: Author
, and
Book
to query these types respectively.
Consider this example:
GraphQL |
EdgeQL equivalent |
---|---|
Copy {
Book {
title
synopsis
author {
name
}
}
} |
Copy SELECT
Book {
title,
synopsis,
author: {
name
}
}; |
The top-level field of the GraphQL query must be a valid name of an object type or an expression alias of something returning an object type. Nested fields must be valid links or properties.
There are some specific conventions as to how arguments in GraphQL queries are used to allow filtering, ordering, and paginating data.
Filtering the retrieved data is done by specifying a filter
argument. The filter
argument is customized to each specific type
based on the available fields. In case of the sample schema, here are
the specifications for available filter arguments for querying Book
:
# this is Book-specific
input FilterBook {
# basic boolean operators that combine conditions
and: [FilterBook!]
or: [FilterBook!]
not: FilterBook
# fields available for filtering (properties in EdgeQL)
title: FilterString
synopsis: FilterString
isbn: FilterString
author: NestedFilterAuthor
}
# this is Author-specific
input NestedFilterAuthor {
# instead of boolean operations, "exists" check is available
# for links
exists: Boolean
# fields available for filtering (properties in EdgeQL)
name: FilterString
}
# this is generic
input FilterString {
# "exists" check is available for every property, too
exists: Boolean
# equality
eq: String
neq: String
# lexicographical comparison
gt: String
gte: String
lt: String
lte: String
# other useful operations
like: String
ilike: String
}
Here are some examples of using a filter:
GraphQL |
EdgeQL equivalent |
---|---|
Copy {
Book(
filter: {
title: {
eq: "Spam"
}
}
) {
title
synopsis
}
} |
Copy SELECT
Book {
title,
synopsis
}
FILTER
Book.title = 'Spam'; |
Copy {
Book(
filter: {
author: {
name: {
eq:
"Lewis Carroll"
}
}
}
) {
title
synopsis
}
} |
Copy SELECT
Book {
title,
synopsis
}
FILTER
Book.author.name =
'Lewis Carroll'; |
It is legal to provide multiple input fields in the same input object. They are all implicitly combined using a logical conjunction. For example:
GraphQL |
EdgeQL equivalent |
---|---|
Copy {
Book(
filter: {
title: {
gte: "m",
lt: "o"
}
}
) {
title
}
} |
Copy SELECT
Book {
title,
}
FILTER
Book.title >= 'm'
AND
Book.title < 'o'; |
It is possible to search for books that don’t specify the author for some reason:
GraphQL |
EdgeQL equivalent |
---|---|
Copy {
Book(
filter: {
author: {
exists: false
}
}
) {
id
title
}
} |
Copy SELECT
Book {
id,
title
}
FILTER
NOT EXISTS
Book.author; |
Ordering the retrieved data is done by specifying an order
argument. The order
argument is customized to each specific type
based on the available fields, much like the filter
. In case of
the sample schema, here are the specifications for the available
filter arguments:
# this is Author-specific
input OrderAuthor {
# fields available for ordering (properties in EdgeQL)
name: Ordering
}
# this is Book-specific
input OrderBook {
# fields available for ordering (properties in EdgeQL)
title: Ordering
synopsis: Ordering
isbn: Ordering
}
# this is generic
input Ordering {
dir: directionEnum
nulls: nullsOrderingEnum
}
enum directionEnum {
ASC
DESC
}
enum nullsOrderingEnum {
SMALLEST # null < any other value
BIGGEST # null > any other value
}
If the value of nulls
is not specified it is assumed to be
SMALLEST
.
GraphQL |
EdgeQL equivalent |
---|---|
Copy {
Author(
order: {
name: {
dir: ASC,
nulls: BIGGEST
}
}
) {
name
}
} |
Copy SELECT
Author {
name,
}
ORDER BY
Author.name ASC
EMPTY LAST; |
Paginating the retrieved data is done by providing one or more of the
following arguments: first
, last
, before
, and after
.
The pagination works in a similar way to Relay Connections. In case of
the sample schema, here are the specifications for the available
filter arguments:
# a relevant Query definition snippet
type Query {
Author(
filter: FilterAuthor,
order: OrderAuthor,
after: String,
before: String,
first: Int,
last: Int,
): [Author!]
# ... other Query fields
}
The after
and before
strings are, in fact, string
representations of numeric indices under the particular filter and
ordering (starting at “0”). This makes the usage fairly intuitive even
without having Relay Connection edges and cursors.
The objects corresponding to the indices specified by before
or
after
are not included.
GraphQL |
EdgeQL equivalent |
---|---|
Copy {
Author(
order: {
name: {
dir: ASC
}
},
first: 10
) {
name
}
} |
Copy SELECT
Author {
name,
}
ORDER BY
Author.name ASC
LIMIT 10; |
Copy {
Author(
order: {
name: {
dir: ASC
}
},
after: "19",
first: 10
) {
name
}
} |
Copy SELECT
Author {
name,
}
ORDER BY
Author.name ASC
OFFSET 20 LIMIT 10; |
Copy {
Author(
order: {
name: {
dir: ASC
}
},
after: "19",
before: "30"
) {
name
}
} |
Copy SELECT
Author {
name,
}
ORDER BY
Author.name ASC
OFFSET 20 LIMIT 10; |