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: FileBaseType
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: FormBaseType
The following fields are available when querying the FormBaseType
:
Field Name | GraphQL Field Type |
---|---|
formTitle | String |
formEmail | String |
formReturnPage | String |
Key/Value Base Type: KeyValueBaseType
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: PageBaseType
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: PersonaBaseType
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: VanityURLBaseType
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: WidgetBaseType
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: Binary
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: Category
Field Name | GraphQL Field Type |
---|---|
inode | String |
active | Boolean |
name | String |
key | String |
keywords | String |
velocityVar | String |
KeyValue Field: KeyValue
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: SiteOrFolder
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 to instances 21.04 and after that upgraded from an earlier version of dotCMS. 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