GraphQL

Gentics Mesh is also able to process GraphQL queries. You can use GraphQL to directly specify what fields should be retrieved and retrieve deeply nested data sets. Internally, Gentics Mesh will resolve your query and traverse your content graph to fetch only the data you specified.

The GraphQL API can thus be used to prepare a single request which returns all data needed to render a specific page.

Possible use cases are:

  • Loading multiple nodes using the webroot path.

  • Generating a custom navigation which only includes the information you need.

  • Invoking multiple search requests to find a set of specific nodes.

  • Resolve links within the content of a node.

  • Load users, roles, groups

  • Load tags, tag families, schema and microschemaModel information

Live Examples

If you want to learn more about the GraphQL syntax take a look at the good documentation.

Loading current user

{ me { username, uuid } }

Loading basic fields of a node

{ node(path: "/yachts/pelorus") { ... on vehicle { fields { name description } } } }

Loading a node via uuid

{ node(uuid: "28f42d43a7604114b42d43a7602114da") { path } }

Loading referenced fields of a node

Nodes can be linked together in various way. One way is the regular parent-child relationship. Another way is by using node fields. The demo data contains vehicles which each is linked to a vehicle image. In order to present the vehicle we also need to retrieve the image path and other information.

{ node(path: "/yachts/pelorus") { ... on vehicle { fields { name description # The vehicleImage field is a node field # which points to a vehicle image node vehicleImage { path # We need to specify what kind of node we expect. # Otherwise we can't retrieve the image # binary field information. ... on vehicleImage { fields { image { width height fileSize mimeType dominantColor } } } } } } } }

Loading incoming references

You can also go the other way and load incoming references..

{ node(path: "/images/yacht-pelorus.jpg") { # Loads incoming references referencedBy { elements { # You can see the field name that was used to reference the node fieldName # And get the referencing node itself. node { uuid path } } } } }

The search query is an escaped JSON object which represents the a regular Elasticsearch query.

{ # Search for all nodes which contain the string 'car' in the content nodes(query: "{\"query\":{\"query_string\":{\"query\":\"car\"}}}") { elements { uuid ... on vehicle { fields { slug } } } # Total amount of found results totalCount } }
Example using variables

Using pagination

Similar to the REST API a value based pagination system is implemented.

{ nodes(perPage: 2, page: 2) { elements { uuid } # Total amount of found elements totalCount # Total amount of found pages. Each page has a size of 2 pageCount # Size of the current page. The last page may only contain a few elements size # Current per page size perPage # Flag which indicates whether another page exists hasNextPage # Flag which indicates whether a previous page exists hasPreviousPage } }

Multilanguage support

The node will automatically be loaded in the language which matches up with the provided webroot path. A webroot path which points to an english node will yield the english content. Subsequent loading a node using the german path will yield the german content. It is important to node that Gentics Mesh tries to stick to a language as much as possible. Loading additional referenced nodes of an german node via either the children or a node field will return the german content if such content could be found. The fallback to the configured default language will be applied if no other matching content found be found. Null will be returned if this also fails.

It is possible to load a found node in a different language using the node field as shown in the example.

{ node(path: "/yachts/pelorus") { availableLanguages node(lang: "de") { language } } }

Filtering

Any time a node list is requested, you can provide a filter object as a parameter to narrow down the result.

Here are a few examples:

Loading nodes from a specific schema

The SchemaFilter matches nodes with a specific schema name.

{ # Loading node with path "/". This is the root folder. node(path: "/") { # Applying a filter on its children. children(filter: { # We filter for the schema with the name category. schema: { is: category } }) { elements { uuid ... on category { fields { name } } } } } }

Filter nodes with regular expressions

The StringFilter offers various ways to filter strings. One example is regular expressions. In this example we get all nodes with the schema vehicle. We check if their name field ends with a number.

{ # Get all nodes and apply filter nodes(filter: { # Get nodes from schema "vehicle" schema: { is: vehicle } # Filter by fields fields: { # If item in result is a "vehicle", # apply this filter vehicle: { # Filter the field "name" with a # regular expression name: { regex: "[0-9]$" } } } }) { elements { uuid ... on vehicle { fields { name } } } } }

Combining different filters

Combine multiple filters to further narrow down your results. One example is the OrFilter. We get the same nodes as in the previous example. Additionally we also get all vehicles that have a price lower than 200.000.

{ # Get all nodes and apply filter nodes(filter: { # Get nodes from schema "vehicle" schema: { is: vehicle } # Filter by fields fields: { # If item in result is a "vehicle", # apply this filter vehicle: { # Test if any of the following filters apply or: [ # Filter the field "name" with a # regular expression {name: { regex: "[0-9]$" }} # Get vehicles that have a price # less than 200.000 {price: { lt:200000 }} ] } } }) { elements { uuid ... on vehicle { fields { name price } } } } }

Filtering limitations

When filtering by fields of a node, it is currently only possible to filter by fields of the following types:

  • string

  • html

  • number

  • date

  • boolean

A note on GraphiQL
Edit the above examples and experiment with the API. Use the GraphiQL autocompletion (press ctrl+space while typing your query) to see what options are available. Check the documentation explorer (in the top-right corner) to find out more details.
Try it in your own installation
Your instance of Gentics Mesh comes with the GraphiQL Browser as well.

Native Filtering

There is a possibility to speed up the filtering by using a native filtering feature, that is applied on a database level. This means that initially less data will be fetched from the database, but at a cost of filtering flexibility, as not every Mesh filter is natively supported.

The native filtering is enabled on Mesh level by The GraphQL Mesh options' new preference nativeQueryFiltering with possible values: * OFF - old runtime filtering. * ALWAYS - DB filtering is forced. * ON_DEMAND - GraphQL parameter nativeFilter is considered for the filtering (default value)

The native filtering itself is controlled by a GraphQL parameter nativeFilter with values: * NEVER - old filtering is forced. * ALWAYS - native DB filtering is forced. If the requested filter is not supported by a DB, an exception is thrown. * IF_POSSIBLE - if the requested filter is supported by a DB, DB filtering is used, otherwise filtering is fallen back to the old filter mechanism (default value).

Sorting

Sorting is possible on selected GraphQL calls, by setting the sort parameter. The sorting request building is analogous to the one for filter parameter, but instead of the filter comparison value, a sorting direction value is used: * ASCENDING * DESCENDING

For instance,

sort: {fields: { mesh_binary_content: {name:ASCENDING}} edited:DESCENDING creator:{lastname:ASCENDING} editor:{emailAddress:DESCENDING}}

Comparison to Elasticsearch

Many tasks can be done by both the search and the filtering feature. Here are a few tips that help you decide which technology is suited best for your needs:

  • GraphQL filtering is independent of Elasticsearch. If you don’t want to use Elasticsearch, GraphQL filtering is still available.

  • GraphQL filtering is faster when dealing with small datasets. There is less overhead compared to Elasticsearch. GraphQL filtering iterates over the source set of elements and applies the filter until enough nodes have been found for the response.

  • Elasticsearch is faster when dealing with large datasets, because it uses an index to access its documents.

  • Elasticsearch is better suited for full text search queries from an end user because you can precisely tune the index to your requirements.

GraphiQL Browser

We have integrated the interactive GraphiQL[1] browser into Gentics Mesh so you can easily play with the API.

Try the example
Live Demo

Alternatively, you can download Gentics Mesh and test the API locally. Once authenticated you can access the interactive GraphiQL browser at /api/v2/:projectName/graphql/browser/ .

The GraphiQL browser currently does not support the branch or version query parameter.

Permission Handling

Generally loading an element in GraphQL with lacking permissions will result in the field to be set to null. Additionally, a permission error will be added to the GraphQL response.

Collection fields will omit the entries to which the user lacks permissions. No errors will be logged in this case.

Nodes

The read_published permission on nodes allows for a finer control on the returned data.

A node will be partially returned (without content) when loading it with version: draft and only readPublished permission was granted on the node. The readPublished permission still grants access to the node data but not the content.

This concept applies differently for collections (.nodes / .node.children / …). In this case the node is completely omitted from the collection. The needed version parameter acts as a filter for these cases. No permission errors will be logged for entries that lack permissions in collections.

Permission behaviour
Permission on node Selected version of content Single Node Node Collection

read

published/draft

Node loaded with content.

Entry included.

read_published

published

Node loaded with content.

Entry included.

read_published

draft

Node loaded without content. Permission error logged.

Entry excluded.

none

published/draft

Node can’t be loaded. Permission error logged.

Entry excluded.

The node.child(path: "") and nodes(path: "") will return null when the content does not match up. See content version handling exceptions for details.

Version Handling

The version parameter on node fields can be used to control whether to return draft or published contents.

Loading single nodes may result in the content being omitted whenever the requested content could not be found or when the permission to read the content is not sufficient. In this case a permission error will be logged in the response.

When loading collections the version parameter acts as a filter and the result will only contain nodes which also have the requested content version.

The selected version argument value will be inherited from the parent element.

Please note that the version parameter can currently not be used to load over content revisions.

Exceptions

The node.child(path: "") and nodes(path: "") are two fields which have a different behaviour since the path is used to directly load a specific content of a node. Whenever the found content does not match up with the specified version parameter no node will be returned. The field will be set to null in those cases.

Slow Query Log

GraphQL queries that take longer than the configured threshold (see GraphQL Options) will be logged with the logger com.gentics.mesh.graphql.SlowQuery with log level WARN.

Limitations

  • At the moment, the GraphQL API can currently only be used for read-only operations. Modifying data with via mutations is currently not supported.

  • GraphQL queries are restricted to a specific project. It is not possible to query data across multiple projects.

  • GraphQL queries are restricted to a specific project branch. The scope of the branch can be changed by adding the ?branch query parameter.


1. GraphiQL is owned and developed by Facebook Inc. Usage is subject to the LICENSE AGREEMENT For GraphiQL software.