GraphQL
GraphQL is an open query language which allows you to perform real-type dynamic queries which specify exactly what data you want, and in what order. You can try it out for yourself in our GraphQL Playground.
The dotCMS GraphQL content delivery API has a number of advantages over querying content via REST:
- A single endpoint to query all content:
api/v1/graphql
. - Self documenting via schema introspection.
- No over-fetching of data (e.g. unneeded fields).
- No need for multiple requests to get combined data.
- Client control over both the query and the data received.
The following sections detail the dotCMS implementation of GraphQL.
Usage#
The dotCMS GraphQL API has a single endpoint: /api/v1/graphql
.
- Queries to the endpoint must be sent as an HTTP
POST
method. - The GraphQL Query is supplied in the
data
portion of the request. - The
content-type
of the request should be set toapplication/json
.
It is recommended that you use a GraphQL-aware tool to test and form your requests to the endpoint. Please see below for an example request.
Authentication#
The GraphQL API accepts the same authentication methods supported by the dotCMS REST API. For more information, please see the REST API Authentication documentation.
Performing a Query#
The data portion of a request to the GraphQL endpoint contains a GraphQL query, which is a string in GraphQL query format. The query must contain one or more Root field, and may also optionally contain arguments and inline fragments.
Root Fields#
Queries can be made using Root fields, which include the Search Root field and Collections. Root fields are fields available at the root of the GraphQL request body:
{ rootField1 rootField2 . . . rootFieldN {
You may combine Root fields in any way you wish, allowing you to perform queries using any of the following:
- The Search Root field alone.
- One or more Collections root fields.
- A combination of one or more Collections and the Search Root field.
General Search (the Search Root field)#
In addition to querying collections of contentTypes or baseTypes, you can query, in a combined way, all content of dotCMS, using the Search Root field, and use inline fragments to fetch data specific to a Content Type or Base Type.
The Search Root field is a GraphQL element that allows you to perform a general Lucene query of the dotCMS content, across all Content Types (and thus all Collections).
Whereas this Lucene query conforms to ElasticSearch behaviors, you may wish to familiarize yourself with the search syntax and how content is mapped to ElasticSearch. For example, when referencing base content types, querying the baseType
collection field will return a string containing the relevant content's base type name; on the other hand, when calling baseType
in a search root field, and thus in a Lucene query, base types are instead fetched through an enumeration and therefore referenced via integers — e.g., +baseType:5
.
Example#
{ search(query: "title:News", limit: 10) { title modDate modUser { firstName lastName } ...on htmlpageasset { url showOnMenu cachettl friendlyname seokeywords pagemetadata } ...on SimpleWidget { widgetCode } ...on FileBaseType { fileName description fileAsset { versionPath idPath name } metaData { key value } } } }
Collections#
All dotCMS Content Types and Base Content Types are available as Collections root fields, using the following usage conventions:
Collection Type | Usage | Example |
---|---|---|
Content Type | {contentTypeVarName}Collection | fileAssetCollection |
Base Content Type | {baseTypeName}BaseTypeCollection | fileBaseTypeCollection |
Querying a Single Collection#
The following GraphQL query demonstrates how to query a single collection:
{ commentsCollection(limit: 10) { title author } }
Querying Multiple Collections#
You can include multiple Collections in the same query, as in the following example:
{ commentsCollection(limit: 10) { title author } blogCollection(limit: 10) { title author } newsCollection(limit: 10) { title lead } }
Arguments#
Arguments allow you to filter the results of Root fields. Arguments are included inside parentheses following the Root field name. Multiple arguments are separated with commas (e.g. rootField(arg1:**value**, arg2:123)
).
The following values may be specified as arguments to each Collection and Search Root field:
Argument | Type | Description |
---|---|---|
query | String | A Lucene query to limit the results returned.
|
limit | Integer | The maximum number of results to return. |
offset | Integer | The offset of the first result to return. |
page | Integer | The page of results to return based on limit and the total number of results; an alternative to offset to achieve pagination. |
sortBy | String | The Velocity variable name of the field(s) to sort by.
|
Inline Fragments#
Inline Fragments allow you to specify the specific Content Type fields you wish to retrieve in your query, and the order to return the fields. This allows you to both limit the amount of data returned, and simplify code maintenance by ensuring that the field order remains the same even if the order of the fields changes in the Content Type.
Usage#
... on {contentTypeOrBaseTypeVarname} { {field1VarName} {field2VarName} . . . {fieldNVarName} }
Example#
The following query searches all content with the word News in the title, and uses inline fragments to fetch only specific fields for returned content of the Page Asset (htmlpageasset) and Widget Content Types:
{ search(query: "title:News", limit: 10) { title modDate modUser { firstName lastName } ...on htmlpageasset { url template showOnMenu sortOrder cachettl friendlyname redirecturl httpsreq seodescription seokeywords pagemetadata } ...on Widget { widgetCode } } }
Exact Matches#
In some cases, you may want an exact match on a query string when retrieving content data, such that it returns an empty result rather than a partial match if the content does not exist. In such a case, for example, if a search for balloon
does not find that exact string, it ought not return a hit for balloon-animals
.
From the Admin Panel#
To accomplish this within the dotCMS production environment, use the dotraw
mapping, such as in the example below. Note that the space must be escaped by way of a double backslash, as the query will be passed next to ElasticSearch, which will needs its own escapes:
query ContentAPI { ProductCollection(query: "+title_dotraw:slow\\ loris") { title } }
From Within an App#
In-app exact-match queries can likewise utilize dotraw
, conducted through block strings, which call for triple quotes:
query ContentAPI { ProductCatalogCollection(query: """+languageId:1 +title_dotraw:fast\\ eddie""") { title } }
Response Pagination#
To manage the size of responses, it is possible to perform pagination through a combination of query arguments and the Pagination
type.
There are two methods of pagination, depending on the use of the arguments page
and offset
:
page
causes the response to bundle all query results into groups of a size determined by thelimit
argument. Thepage
argument accepts an integer value, starting with 1, causing the response to return the indicated group of results.offset
skips a specified number of results. This can be used programmatically to implement more granular page behaviors.- Where
page
andoffset
are both specified,page
overrulesoffset
; the latter is replaced by the result of the formula[(page-1)*limit]
.
- Where
Through the Pagination
type, it is possible to view information about the response pagination. Note that this type must be specified outside of the search query.
For example:
query { search( query: "+contentType:activity", limit: 5, page: 2, sortBy:"title" ){ identifier title ...on Activity { description urlTitle tags } } Pagination { fieldName totalPages totalRecords pageRecords hasNextPage hasPreviousPage pageSize page offset } }
Types and Fields#
There are various content structures or Types
in the system which can be accessed via GraphQL. Some of these correspond to dotCMS Content Types, while others correspond to other types of dotCMS objects. The following sections define all the different Types
in the system and the various system or custom fields that are or can be associated with each Type
Root Type — Contentlet (Search Root field only)#
If you use the Search Root field, the resulting items will be of the root type Contentlet.
The Contentlet root type has a number of fields available for all content, regardless of its Base Type or Content Type:
Field Name | Field Type |
---|---|
modDate | String |
title | String |
titleImage | Binary* |
contentType | String (type var name) |
baseType | String (base type name) |
live | Boolean |
working | Boolean |
archived | Boolean |
locked | Boolean |
conLanguage | Language* |
identifier | String |
inode | String |
folder | Folder* |
host | Site* |
owner | User* |
modUser | User* |
* GraphQL Custom Type: Please check the Custom Types section for the fields available in values of this type.
Working/Draft Retrieval#
Setting working
to true
will result in the retrieval of working contentlets — a.k.a., drafts. However, this call will only succeed if the caller is authenticated as a back-end user, consistent with the behavior of the Content API.
Base Types#
Base Types allow you to fetch values for the fields in all Content Types created from the corresponding Base Content Type.
Base Types are available as Collections, or via Inline fragments when using the Search Root field.
- When fetching content using the Base Types Interfaces, the only fields returned are the System fields of the selected Base Types.
- Any additional custom fields added to the individual Content Types of the content will not be returned.
- The System Fields available for each Base Type may change in future versions.
- The following sections show the fields currently available to each Base Type.
- However, you should view the appropriate Base Types in the Content Type editor in your current dotCMS version to identify which fields are System Fields.
File Base Type#
The following fields are available when querying the FileBaseType
:
Field Name | GraphQL Field Type | Notes |
---|---|---|
fileName | String | |
description | String | |
fileAsset | Binary | |
metaData | List of KeyValue | |
showOnMenu | List of String | Checkbox field values are returned as List of String, since a single Checkbox field can contain multiple values. The value of the showOnMenu field is returned as [ "true" ] if true, or [] if false. |
sortOrder | Integer |
Form Base Type#
The following fields are available when querying the FormBaseType
:
Field Name | GraphQL Field Type |
---|---|
formTitle | String |
formEmail | String |
formReturnPage | String |
Key/Value Base Type#
The following fields are available (for each Key/Value pair) when querying the KeyValueBaseType
:
Field Name | GraphQL Field Type |
---|---|
key | String |
value | String |
Note:
- The GraphQL KeyValue Type represents a single Key/Value pair, not the entire contents of the field.
- Therefore the value of a Key/Value field is returned as a list of GraphQL KeyValue object, not as a single object.
Page Base Type#
The following fields are available when querying the PageBaseType
:
Field Name | GraphQL Field Type | Notes |
---|---|---|
url | String | |
template | String | Identifier of the Template assigned to the Page |
showOnMenu | List of String | Checkbox field values are returned as List of String. The value of the showOnMenu field is returned as [ "true" ] if true, or [] if false. |
sortOrder | Integer | |
cachettl | String | Returned as a string representing the (integer) value. |
friendlyname | String | |
redirecturl | String | |
httpsreq | List of String | Checkbox field values are returned as List of String. The value of the httpsreq field is returned as [ "true" ] if true, or [] if false. |
seodescription | String | |
seokeywords | String | |
pagemetadata | String |
Persona Base Type#
The following fields are available when querying the PersonaBaseType
:
Field Name | GraphQL Field Type |
---|---|
name | String |
keyTag | String |
photo | Binary |
tags | List of String |
description | String |
Vanity URL Base Type#
The following fields are available when querying the VanityURLBaseType
:
Field Name | GraphQL Field Type |
---|---|
url | String |
forwardTo | String |
action | String |
order | Integer |
Widget Base Type#
The following fields are available when querying the WidgetBaseType
:
Field Name | GraphQL Field Type |
---|---|
widgetTitle | String |
widgetCode | String |
widgetUsage | String |
widgetPreexecute | String |
Content Types#
Every Content Type defined in dotCMS is available as a GraphQL Type.
- The name of the GraphQL Type matches the variable name of the dotCMS Content Type.
- All fields of each Content Type are available when accessing the content using the Content Type.
- Each field type is mapped to an appropriate GraphQL Type, as shown in the table below.
GraphQL Types for dotCMS Field Types#
All GraphQL Types corresponding to Content Type fields are automatically generated by the dotCMS GraphQL interface at the time a query is received.
dotCMS Field Type | GraphQL Type | Notes |
---|---|---|
Binary | Binary | |
Category | Category | |
Checkbox | List of String | Each Checkbox field can contain multiple values (like a Multiselect), so the values are returned as a List of Strings rather than as true/false. |
DateTime | String | Formatted using the format YYYY-MM-DD hh:mm:ss.sss (e.g. 2019-03-13 14:19:21.815 ). |
File | Binary | |
Host Or Folder | SiteOrFolder | |
Image | Binary | |
Key/Value | List of KeyValue | |
Multiselect | List of String | |
Tag | List of String | |
Time | String | Formatted using the format YYYY-MM-DD hh:mm:ss.sss , with the year set to 1970 (e.g. 1970-01-01 14:19:21.815 ). |
All Others | String |
Custom GraphQL Types#
The following GraphQL types are defined by the dotCMS GraphQL implementation, and represent dotCMS field types which don't map directly to standard data types. These GraphQL Types allow you to access individual properties of the appropriate dotCMS fields similar to the way you can access these properties when working with the field values in Velocity or Java.
Binary Field#
Field Name | GraphQL Field Type | Notes |
---|---|---|
versionPath | String | Returns the short version of the inode-based URI for the content. Similar to calling .getShortyUrlInode on a content object. |
idPath | String | Returns the short version of the identifier-based URI for the content. Similar to calling .getShortyUrl . |
name | String | Returns the file name of the stored binary. |
size | Long | |
mime | String | |
isImage | Boolean |
Category Field#
Field Name | GraphQL Field Type |
---|---|
inode | String |
active | Boolean |
name | String |
key | String |
keywords | String |
velocityVar | String |
KeyValue Field#
Field Name | Field Type |
---|---|
key | String |
value | String |
Note:
- The GraphQL KeyValue Type represents a single Key/Value pair, not the entire contents of the field.
- Therefore the value of a Key/Value field is returned as a list of GraphQL KeyValue object, not as a single object.
Site or Folder Field#
Field Name | GraphQL Field Type |
---|---|
folderId | String |
folderFileMask | String |
folderSortOrder | Integer |
folderName | String |
folderPath | String |
folderTitle | String |
folderDefaultFileType | String |
hostId | String |
hostName | String |
hostAliases | String |
hostTagStorage | String |
Additional Custom Types #
These GraphQL Types are used to represent objects which do not represent dotCMS content, and which are not used for specific dotCMS field types. These objects are returned as part of some content objects which may be returned by GraphQL queries.
Folder #
Field Name | GraphQL Type | Notes |
---|---|---|
folderId | String | |
folderFileMask | String | |
folderSortOrder | Integer | |
folderName | String | |
folderPath | String | |
folderTitle | String | |
folderDefaultFileType | String | Identifier of the folder's Default Content Type |
Language #
Field Name | GraphQL Type |
---|---|
id | Integer |
languageCode | String |
countryCode | String |
language | String |
country | String |
Site #
Field Name | GraphQL Type | Notes |
---|---|---|
hostId | String | |
hostName | String | |
hostAliases | String | |
hostTagStorage | String | Identifier of the Site the tags are stored on |
User#
Field Name | GraphQL Type |
---|---|
userId | String |
firstName | String |
lastName | String |
email | String |
Pagination Type#
Field Name | GraphQL Type | Notes |
---|---|---|
fieldName | String | Name of field. |
totalPages | Integer | Number of pages based on limit and totalRecords . |
totalRecords | Integer | Total number of query results, including those not returned due to pagination limits. |
pageRecords | Integer | Results on the current page. |
hasNextPage | Boolean | False if the current page is the final page of results. |
hasPreviousPage | Boolean | False if the current page is the first page of results. |
pageSize | Integer | The number of results per page, adjusted with limit argument. Default: 100 |
page | Integer | Page number, according to page argument. One of two methods of result pagination. |
offset | Integer | Number of results skipped, using offset argument. One of two methods of result pagination. |
Caching GraphQL Queries#
GraphQL results are cached to improve performance. The cached values will be checked at the time of each query, and will be regenerated if the underlying dotCMS objects have changed.
Note: The history of changes to a Content Type are not tracked at the level of individual fields. This means that any changes made to a Content Type's properties or any of its fields will cause all GraphQL types to be regenerated the next time a GraphQL query is received.
The cache default properties are as follows:
Attribute | Type | Value |
---|---|---|
Cache Key | String | Same as query |
TTL (Seconds) | Int | 15 |
Size (Bytes) | Int | 5000 |
Both of the above numeric values can be reconfigured through the following environment variables:
DOT_CACHE_GRAPHQLQUERYCACHE_SECONDS
DOT_CACHE_GRAPHQLQUERYCACHE_SIZE
Configuration Options at Request Time#
In addition to the region settings above, the following settings can also be specified inside of an individual GraphQL query.
Custom Key#
dotcachekey
By providing the argument dotcachekey
either as a request parameter or a header, a custom cache key may be specified. This replaces the default cache key, which is usually the GraphQL query, itself.
Custom TTL#
dotcachettl
Configuration of TTL at request time is best used in conjunction with a relatively long TTL in the general cache region, to minimize the effect of events such as unexpected invalidations. One recommendation to this end would be to set DOT_CACHE_GRAPHQLQUERYCACHE_SECONDS
to at least twice the maximum TTL likely to be specified at request time.
By sending the dotcachettl
argument either as request parameter or request header, you may specify a new expiration time in seconds. This argument can take two special values:
Value | Effect |
---|---|
0 | Bypasses the cache |
-1 | Bypasses the cache and clears the entry for a given key or query |
Dirty Reads#
dotcacherefresh
Providing dotcacherefresh
as a request-time argument, parameter, or header will result in a "dirty read" from the appropriate cache key. This results in quicker responses and less overhead at the expense of accuracy, as a cache may be read while in the process of updating its value under conditions of high concurrency.
This feature is most safely used while fetching queries that are unlikely to change often, or when accuracy is not a high priority.
Example#
The following curl command performs a GraphQL query which returns the "title" and "showOnMenu" fields (only) of the first 10 File Assets using the default sort order:
curl --request POST \
--url http://localhost:8082/api/v1/graphql \
--header 'content-type: application/json' \
--data '{"query":"{\n fileAssetCollection(limit: 10) {\n title\n showOnMenu\n }\n}"}'
Note:
- This is provided purely as an example to demonstrate the method and headers required to access the endpoint.
- It is recommended that you test the GraphQL endpoint using a GraphQL-aware client rather than curl.
Testing and Debugging#
GraphQL Tools#
dotCMS has built a GraphQL playground to construct and test GraphQL queries. This playground is available under dev tools in new builds 21.04 and after. It can also be added under Roles and Tools. The GraphQL tool is also available under dev tools on the dotCMS Demo Site. Do keep in mind that the demo site refreshes every 12 hours so you will lose your work at that point. Finally, you can use the playground on the dotCMS website.
A number of third-party tools also exist to construct and test GraphQL queries. You may wish to test the dotCMS GraphQL interface using GraphQL-aware clients such as Insomnia or Altair.
Printing the GraphQL Schema#
The GraphQL Schema can be printed for debugging purposes by including GRAPHQL_PRINT_SCHEMA=true
in the dotmarketing-config.properties file. Changes to the dotmarketing-config.properties file should be made in a configuration plugin.
GRAPHQL_PRINT_SCHEMA=true