Skip to content

GraphQL

Sample queries

Available since: v3.1.0

From SurrealDB 3.1.0, SurrealDB’s GraphQL layer uses Apollo-style names: a pluralised list field (for example persons for table person), a singular fetch field person(id: …), and persons_aggregate for aggregates. Internally these map to SurrealQL-style reads (typically SELECT). The SurrealQL here is a rough equivalent for the same or similar data shape. See GraphQL overview for the full naming table.

Before trying the examples, enable GraphQL and define data in the current namespace and database (see GraphQL overview using DEFINE CONFIG GRAPHQL AUTO). The snippets below assume:

  • Namespace main, database main

  • Root authentication root / secret

  • A person table with name and age, and records person:simon and person:marcus as in GraphQL via HTTP

Schema and sample data
DEFINE TABLE person SCHEMAFULL;
DEFINE FIELD name ON TABLE person TYPE string;
DEFINE FIELD age ON TABLE person TYPE number;
CREATE person:simon SET name = "Simon", age = 23;
CREATE person:marcus SET name = "Marcus", age = 28;
DEFINE CONFIG GRAPHQL AUTO;

GraphQL here returns a list of objects, similar to SELECT without ONLY.

Query
query {
	persons {
		name
		age
	}
}
Output
{
	"data": {
		"persons": [
			{
				"age": 28,
				"name": "Marcus"
			},
			{
				"age": 23,
				"name": "Simon"
			}
		]
	}
}

Use person(id: …) with the record key (simon, not person:simon in the argument). The GraphQL id field on the result is the full record id.

Query
query {
	person(id: "simon") {
		id
		name
		age
	}
}
Output
{
	"data": {
		"person": {
			"id": "person:simon",
			"name": "Simon",
			"age": 23
		}
	}
}

GraphQL uses limit (and optional start for offset). SurrealQL uses LIMIT / START and ONLY to return a single record as opposed to an array containing a single record.

Query
query {
	persons(limit: 1) {
		name
		age
	}
}
Output
{
	"data": {
		"persons": [
			{
				"age": 28,
				"name": "Marcus"
			}
		]
	}
}

Available since: v3.1.0

personsConnection takes first and after to page forwards, or last and before to page backwards. Passing both first and last returns the error Pass either `first` or `last`, not both, and the same applies to after and before. The default page size is 20, and a size above 1000 is reduced to 1000.

A cursor is the base64 encoding of the record id, so paging follows record id order. The order argument of the list query does not apply to a connection. The totalCount field runs a separate count, and only when the query selects it.

Query
query {
	personsConnection(first: 1) {
		edges {
			cursor
			node {
				name
			}
		}
		pageInfo {
			hasNextPage
			endCursor
		}
		totalCount
	}
}
Output
{
	"data": {
		"personsConnection": {
			"edges": [
				{
					"cursor": "cGVyc29uOm1hcmN1cw",
					"node": {
						"name": "Marcus"
					}
				}
			],
			"pageInfo": {
				"hasNextPage": true,
				"endCursor": "cGVyc29uOm1hcmN1cw"
			},
			"totalCount": 2
		}
	}
}

Passing the endCursor as after returns the next page:

Query
query {
	personsConnection(first: 1, after: "cGVyc29uOm1hcmN1cw") {
		edges {
			node {
				name
			}
		}
		pageInfo {
			hasNextPage
		}
	}
}
Output
{
	"data": {
		"personsConnection": {
			"edges": [
				{
					"node": {
						"name": "Simon"
					}
				}
			],
			"pageInfo": {
				"hasNextPage": false
			}
		}
	}
}

GraphQL accepts filter or where with the generated input type for the table. For a scalar field, use comparison keys such as eq, ne, gt, and lt where the schema allows them.

The id field can be filtered too, but it takes the full record id, so persons(where: { id: { eq: "person:simon" } }) returns Simon, while "simon" fails with Error converting value: "simon" to type: record. This is the opposite of person(id: …), which takes only the record key and returns null when given person:simon.

Query
query {
	persons(where: { age: { eq: 23 } }) {
		name
	}
}
Output
{
	"data": {
		"persons": [
			{
				"name": "Simon"
			}
		]
	}
}

From SurrealDB 3.1.0, the id filter accepts eq, ne, in, gt, gte, lt, lte and a range input with from, to and inclusive. A relation field accepts count, which takes the same comparison keys as a number. This query returns the people with at least one outgoing sent relation:

Query
query {
	persons(filter: { sent: { count: { gt: 0 } } }) {
		name
	}
}
Output
{
	"data": {
		"persons": [
			{
				"name": "Simon"
			}
		]
	}
}

Use an order argument with asc or desc and a field name.

Query
query {
	persons(order: { asc: age }) {
		name
		age
	}
}
Output
{
	"data": {
		"persons": [
			{
				"age": 23,
				"name": "Simon"
			},
			{
				"age": 28,
				"name": "Marcus"
			}
		]
	}
}

For the full configuration surface (tables, functions, limits), see DEFINE CONFIG GRAPHQL.

Was this page helpful?