This section aims to provide the working details of the GraphQL API that can be used to query your Realm Object Server. It is important to note that you will need to properly authenticate a user before consuming data with the API.
The GraphQL endpoint is mounted on /graphql/:path
where path is the relative path of the Realm.
The GraphQL subscription endpoint is ws://ROS-URL:ROS-PORT/graphql/:path
.
The GraphQL schema endpoint is /graphql/schema/:path
where path is the relative path of the Realm.
The GraphiQL Explorer (visual exploratory tool) endpoint is mounted on /graphql/explore/:path
where path, again, is the path of the Realm.
By default, all endpoints and actions are authenticated.
If you wish to disable authentication while developing, you can pass disableAuthentication: true
to the service constructor. This is only possible if self-hosting the server and is meant strictly for usage during development.
Authentication is done with an Access Token, obtained by executing POST request against the /auth
endpoint:
First, you'll need to login the user with their provider. For example, when authenticating with username/password, pass the following payload:
{"app_id":"","provider":"password","data":"MY-USERNAME","user_info": {"register":false,"password":"MY-PASSWORD"}}
The response will look something like:
{"refresh_token": {"token":"VERY-LONG-TOKEN-HERE"}}
We'll need the refresh token to obtain the access token by posting again to /auth
:
{"app_id":"","provider":"realm", // Note provider is 'realm'"data":"REFRESH_TOKEN.TOKEN", // Token from previous response"path":"REALM-PATH" // Path of the realm you want to access, e.g. '/user-id/tickets}
The response will now contain:
{"access_token": {"token":"VERY-LONG-TOKEN-HERE"},"token_data": {"expires": 1512402618 // unix timestamp}}
We'll need this access token to perform all graphql actions. This token must be refreshed before it expires using the refresh token obtained earlier to avoid getting 401: Unauthorized
responses.
Queries are regular GET/POST requests and require standard authorization headers.
Authorization: ACCESS_TOKEN.TOKEN
To query, you start with a query
node. The schema of the Realm file is automatically used to generate the GraphQL schema that exposes the following operations:
Query for all objects of a certain type: all object types have a pluralized node, e.g. users
, accounts
, etc. It accepts the following optional arguments:
query
: a verbatim realm.js query that will be used to filter the returned dataset.
sortBy
: a property on the object to sort by.
descending
: sorting direction (default is false
, i.e. ascending).
skip
: offset to start taking objects from.
take
: maximum number of items to return.
Query for object by primary key: object types that have a primary key defined will have a singularized node, e.g. user
, realmFile
, etc. It accepts a single argument that is the primary key of the object.
Inverse relationships: all models expose a function called _linkingObjects
that allows you to query for objects that link to the current one. Since GraphQL doesn't have true generic support, the return type is a union so you'll need to switch on the target object type. Depending on the value of includeCountInResponses
in the service config, the return type on which you need to switch is either *TargetType*Collection
or *TargetType*
:
query {users {namebirthdaydogs:_linkingObjects(objectType:"Dog" property: "owner") {...on Dog {namebreed}}}}
For models which already have a plural name definition in your schema, you will need to add another "s" to your query. (i.e. "cars" becomes "carss", "data" becomes "datas", etc)
For more information on how to use query
see the GraphQL documentation.
Mutations are regular GET/POST requests and require standard authorization headers.
Realm automatically generates acreate<ObjectType>
and adelete<ObjectType>
mutation for each object type in a realm. For example, a Realm that contains User
and Account
object has createUser
, deleteUser
, createAccount
and deleteAccount
mutations. You can use the automatically generated mutations to create, update, and delete objects in a realm.
For information on how to write and use a mutation
, refer to the official GraphQL documentation.
To add an object to a realm, use the create<ObjectType>
mutation for the object type and specify the object in the input
parameter with the appropriate<ObjectType>Input
input type.
mutation CreateNewUser($user: UserInput!) {createUser(input: $user) {name}}
To add multiple instances of an object type, use the create<ObjectType>s
mutation for the object type and specify the objects in the input
parameter as an array of the appropriate <ObjectType>Input
input type.
mutation CreateNewUsers($users: [UserInput]!) {createUsers(input: $users) {name}}
Realm automatically adds any related objects that you include in the input, e.g. if you specify threeaccounts
in the addUser
input, Realm will also add the account objects.
To update an object, use the create<ObjectType>
mutation for the object type with a value set for the updatePolicy
parameter. Specify the object in the input
parameter with the appropriate<ObjectType>Input
input type.
mutation UpdateExistingUser($user: UserInput!) {createUser(input: $user, updatePolicy: MODIFIED) {name}}
To update multiple instances of an object type, use the create<ObjectType>s
mutation for the object type with a value set for the updatePolicy
parameter. Specify the objects in the input
parameter as an array of the appropriate <ObjectType>Input
input type.
mutation UpdateExistingUsers($users: [UserInput]!) {createUsers(input: $users, updatePolicy: MODIFIED) {name}}
The value of updatePolicy
determines how Realm handles the update operation. You may choose any of the following update policies:
Policy | Description |
NONE | Creates the object if no existing object has the same primary key, or throws an error otherwise. |
MODIFIED | Updates only those properties that are different between the input and the specified object. |
ALL | Realm should fully replace the specified object with the provided input. |
If an object type has a primary key, use the delete<ObjectType>
mutation for the object type and specify the object's primary key value in the id
parameter. The mutation returns true
if the object was deleted, and false
if no existing object has the specified primary key.
mutation DeleteUser($userId: String!) {deleteUser(id: $userId)}
To delete one or more objects of an object type, use the delete<ObjectType>s
mutation for the object type and specify a realm-js query in the query
parameter. The mutation deletes all objects that match the specified query. If you omit the query
parameter, then the mutation deletes all objects of the specified type. The mutation returns the number of objects that were deleted.
mutation DeleteUsers($query: String!) {deleteUsers(query: $query)}
Use DELETE /graphql/schema/:path
to clear the cached schema of the Realm at path
if schema caching is enabled (e.g. due to a recent schema change).
Subscriptions use websocket connections, which require authentication after the connection is established before any GraphQL-related message can be sent.
Before sending any graphql-related messages, you'll need to send an object message, containing an authToken
field set to the access token:
{token: ACCESS_TOKEN.TOKEN}
To subscribe for change notifications, start with a subscription
node. The schema of the Realm file is automatically used to generate the GraphQL schema that exposes the following operations:
Subscribing for queries: all object types have a pluralized node, e.g. users
, accounts
, etc. Every time an item is added, deleted, or modified in the dataset, the updated state will be pushed via the subscription socket. The node accepts the following optional arguments:
query
: a verbatim realm.js query that will be used to filter the returned dataset.
sortBy
: a property on the object to sort by.
descending
: sorting direction (default is false
, i.e. ascending).
skip
: offset to start taking objects from.
take
: maximum number of items to return.
IMPORTANT NOTE ON TOKEN VALIDATION: The access token for subscriptions is validated only when the socket connection is established and not when emitting notifications by the server. This means that it's the client's responsibility to terminate the connection if the user logs out or loses access to the Realm.
​