Query the GraphQL API
This guide assumes you have a working knowledge of GraphQL query syntax. For a general overview of GraphQL, please refer to the documentation (opens in a new tab).
Ponder uses your schema.graphql
file to generate a GraphQL API for your app. With the dev server running, open http://localhost:42069
in your browser to use the GraphiQL (opens in a new tab) interface. GraphiQL is a useful tool for exploring your schema and testing queries during development.
Schema generation
Ponder creates a singular and a plural query field for each entity type in your schema. For example, if your schema contains a Person
entity, Ponder will create a person
and a persons
field on the root Query
type. The singular query field returns a single entity (or null), while the plural query field returns a list of entities.
type Person @entity {
id: Int!
name: String!
age: Int!
}
type Query {
person(id: Int!, timestamp: Int): Person
persons(
skip: Int = 0
first: Int = 100
orderBy: String = "id"
orderDirection: String = "asc"
where: PersonFilter,
timestamp: Int
): [Person!]!
}
Filtering
The GraphQL API supports filtering through the where
argument. The where
argument type contains filter options for every field defined on your entity. Here are the filter options available for each field type.
Filter option | Available for field types | Include entities where... |
---|---|---|
{field} | All | {field} equals the specified value |
{field}_not | All | {field} does not equal the specified value |
{field}_in | Scalars, enums, one-to-one relationships | {field} is one of the specified values |
{field}_not_in | Scalars, enums, one-to-one relationships | {field} is not one of the specified values |
{field}_contains | Lists of scalars and enums | {field} contains the specified value as an element |
{field}_not_contains | Lists of scalars and enums | {field} does not contain the specified value as an element |
{field}_gt | Numeric scalars (Int, Float, BigInt) | {field} is greater than specified value |
{field}_lt | Numeric scalars (Int, Float, BigInt) | {field} is less than specified value |
{field}_gte | Numeric scalars (Int, Float, BigInt) | {field} is greater than or equal to specified value |
{field}_lte | Numeric scalars (Int, Float, BigInt) | {field} is less than or equal to specified value |
{field}_starts_with | String scalars (String, Bytes) | {field} is starts with specified value |
{field}_not_starts_with | String scalars (String, Bytes) | {field} is does not start with specified value |
{field}_ends_with | String scalars (String, Bytes) | {field} is ends with specified value |
{field}_not_ends_with | String scalars (String, Bytes) | {field} is does not end with specified value |
For all following examples, assume these entities exist in your database.
[
{ "id": 1, "name": "Barry", "age": 57 },
{ "id": 2, "name": "Lucile", "age": 32 },
{ "id": 3, "name": "Sally", "age": 22 },
{ "id": 4, "name": "Pablo", "age": 71 },
]
Get all Person
entities with an age
greater than 32
:
query {
persons(where: { age_gt: 32 }) {
name
age
}
}
{
"persons": [
{ "name": "Barry", "age": 57 },
{ "name": "Pablo", "age": 71 },
]
}
Get all Person
entities with a name
that does not end with "y"
:
query {
persons(where: { name_not_ends_with: "y" }) {
name
age
}
}
{
"persons": [
{ "name": "Lucile", "age": 32 },
{ "name": "Pablo", "age": 71 },
]
}
Pagination
The GraphQL API supports pagination through the first
and skip
arguments.
Pagination option | Default | Max |
---|---|---|
first | 100 | 1000 |
skip | 0 | 5000 |
query {
persons(first: 2, skip: 1) {
name
age
}
}
{
"persons": [
{ "name": "Lucile", "age": 32 },
{ "name": "Sally", "age": 22 },
]
}
The default and max first
and skip
values are also applied to derived
fields. If you find
youself needing to paginate through more than 1000 items in a derived field,
strongly consider writing a new query that fetches those items at the root
level.
Sorting
Use the orderBy
and orderDirection
arguments to sort entities by a scalar field. String scalars (String, Bytes) use a lexicographic sort.
Pagination option | Default |
---|---|
orderBy | "id" |
orderDirection | "asc" |
query {
persons(orderBy: "age", orderDirection: "desc") {
name
age
}
}
{
"persons": [
{ "name": "Pablo", "age": 71 },
{ "name": "Barry", "age": 57 },
{ "name": "Lucile", "age": 32 },
{ "name": "Sally", "age": 22 },
]
}
Time-travel queries
Using time-travel queries, you can query the state of your app's database at any point in history. To construct a time-travel query, pass a Unix timestamp to the timestamp
argument on any of the root query types.
Time-travel option | Default |
---|---|
timestamp | undefined ("latest") |
In this example, consider that only Pablo had been added to the database at the specified timestamp, and his age at that time was 42. The other entities were inserted later.
query {
persons(timestamp: 1689910567) {
name
age
}
}
{
"persons": [
{ "name": "Pablo", "age": 42 },
]
}
Derived fields
Derived fields return the list of child/derived entities that "belong" to the parent. They're very similar to the plural query field that, except derived fields are automatically filtered by the parent's ID.
type Person @entity {
id: Int!
pets: [Pet!]! @derivedFrom(field: "ownerId")
}
type Pet @entity {
id: Int!
name: String!
ownerId: Int!
}
type Query {
# ...
persons(
skip: Int = 0
first: Int = 100
orderBy: String = "id"
orderDirection: String = "asc"
where: PersonFilter,
timestamp: Int
): [Person!]!
}
type Person {
id: Int!
pets(
skip: Int = 0
first: Int = 100
orderBy: String = "id"
orderDirection: String = "asc"
where: PetFilter, # This automatically has { ownerId: person.id } applied
timestamp: Int
): [Pet!]!
}