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 to application/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 TypeUsageExample
Content Type{contentTypeVarName}CollectionfileAssetCollection
Base Content Type{baseTypeName}BaseTypeCollectionfileBaseTypeCollection
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:

ArgumentTypeDescription
queryStringA Lucene query to limit the results returned.
  • This parameter is required for Search Root Fields.
limitIntegerThe maximum number of results to return.
offsetIntegerThe offset of the first result to return.
pageIntegerThe page of results to return based on limit and the total number of results; an alternative to offset to achieve pagination.
sortByStringThe Velocity variable name of the field(s) to sort by.
  • Multiple sort fields are separated by commas.
  • Each field may be followed by asc or desc to specify the sort order of that field (asc is the default).

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 the limit argument. The page 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 and offset are both specified, page overrules offset; the latter is replaced by the result of the formula [(page-1)*limit].

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 NameField Type
modDateString
titleString
titleImageBinary*
contentTypeString (type var name)
baseTypeString (base type name)
liveBoolean
workingBoolean
archivedBoolean
lockedBoolean
conLanguageLanguage*
identifierString
inodeString
folderFolder*
hostSite*
ownerUser*
modUserUser*

* 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 NameGraphQL Field TypeNotes
fileNameString
descriptionString
fileAssetBinary
metaDataList of KeyValue
showOnMenuList of StringCheckbox 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.
sortOrderInteger

Form Base Type#

The following fields are available when querying the FormBaseType:

Field NameGraphQL Field Type
formTitleString
formEmailString
formReturnPageString

Key/Value Base Type#

The following fields are available (for each Key/Value pair) when querying the KeyValueBaseType:

Field NameGraphQL Field Type
keyString
valueString

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 NameGraphQL Field TypeNotes
urlString
templateStringIdentifier of the Template assigned to the Page
showOnMenuList of StringCheckbox field values are returned as List of String.
The value of the showOnMenu field is returned as [ "true" ] if true, or [] if false.
sortOrderInteger
cachettlStringReturned as a string representing the (integer) value.
friendlynameString
redirecturlString
httpsreqList of StringCheckbox field values are returned as List of String.
The value of the httpsreq field is returned as [ "true" ] if true, or [] if false.
seodescriptionString
seokeywordsString
pagemetadataString

Persona Base Type#

The following fields are available when querying the PersonaBaseType:

Field NameGraphQL Field Type
nameString
keyTagString
photoBinary
tagsList of String
descriptionString

Vanity URL Base Type#

The following fields are available when querying the VanityURLBaseType:

Field NameGraphQL Field Type
urlString
forwardToString
actionString
orderInteger

Widget Base Type#

The following fields are available when querying the WidgetBaseType:

Field NameGraphQL Field Type
widgetTitleString
widgetCodeString
widgetUsageString
widgetPreexecuteString

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 TypeGraphQL TypeNotes
BinaryBinary
CategoryCategory
CheckboxList of StringEach Checkbox field can contain multiple values (like a Multiselect), so the values are returned as a List of Strings rather than as true/false.
DateTimeStringFormatted using the format YYYY-MM-DD hh:mm:ss.sss (e.g. 2019-03-13 14:19:21.815).
FileBinary
Host Or FolderSiteOrFolder
ImageBinary
Key/ValueList of KeyValue
MultiselectList of String
TagList of String
TimeStringFormatted 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 OthersString

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 NameGraphQL Field TypeNotes
versionPathStringReturns the short version of the inode-based URI for the content. Similar to calling .getShortyUrlInode on a content object.
idPathStringReturns the short version of the identifier-based URI for the content. Similar to calling .getShortyUrl.
nameStringReturns the file name of the stored binary.
sizeLong
mimeString
isImageBoolean

Category Field#

Field NameGraphQL Field Type
inodeString
activeBoolean
nameString
keyString
keywordsString
velocityVarString

KeyValue Field#

Field NameField Type
keyString
valueString

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 NameGraphQL Field Type
folderIdString
folderFileMaskString
folderSortOrderInteger
folderNameString
folderPathString
folderTitleString
folderDefaultFileTypeString
hostIdString
hostNameString
hostAliasesString
hostTagStorageString

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 NameGraphQL TypeNotes
folderIdString
folderFileMaskString
folderSortOrderInteger
folderNameString
folderPathString
folderTitleString
folderDefaultFileTypeStringIdentifier of the folder's Default Content Type

Language #

Field NameGraphQL Type
idInteger
languageCodeString
countryCodeString
languageString
countryString

Site #

Field NameGraphQL TypeNotes
hostIdString
hostNameString
hostAliasesString
hostTagStorageStringIdentifier of the Site the tags are stored on

User#

Field NameGraphQL Type
userIdString
firstNameString
lastNameString
emailString

Pagination Type#

Field NameGraphQL TypeNotes
fieldNameStringName of field.
totalPagesIntegerNumber of pages based on limit and totalRecords.
totalRecordsIntegerTotal number of query results, including those not returned due to pagination limits.
pageRecordsIntegerResults on the current page.
hasNextPageBooleanFalse if the current page is the final page of results.
hasPreviousPageBooleanFalse if the current page is the first page of results.
pageSizeIntegerThe number of results per page, adjusted with limit argument. Default: 100
pageIntegerPage number, according to page argument. One of two methods of result pagination.
offsetIntegerNumber 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:

AttributeTypeValue
Cache KeyStringSame as query
TTL (Seconds)Int15
Size (Bytes)Int5000

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:

ValueEffect
0Bypasses the cache
-1Bypasses 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