Skip to main content

GraphQL filter

The GraphQL API lets you list, sort and filter your content. You can choose the sort order of your results and filter content using one or more custom properties.

On this page we'll explain how to use the GraphQL filter functionality, including how to list, sort and filter content. We will provide examples for how to perform each of these actions. Alongside the examples we have also provided a number of schema examples and code snippets so that you can try them out on your own hub.

You can try out any of the examples on this page, or your own queries, on our Amplience examples playground

Naming
Link copied!

The name you give your content type schema is what will be used to query your content in GraphQL. This is because the graphs in GraphQL are created by converting all content type schemas for a given hub into a single GraphQL schema, known as a graph. For example, if you were to create a new content type schema and use the name 'blog post' at the end of the URI path (i.e. after the last "/"), your content type schema would be known as 'BlogPost' in GraphQL.

At the same time, a GraphQL query is created to allow users to filter by content type. The GraphQL types created to be used for filter by type queries prefix the single GraphQL type name with "all" and camelCase the single GraphQL type name.

Some examples below:

content type schema nameGraphQL nameGraphQL Filter name
authorauthorallAuthor
BlogPostblogpostallBlogPost
MediamediaallMedia

For more examples and information about the naming process, click here.

GraphQL arguments
Link copied!

Arguments
Link copied!

Filter by content type queries support four different arguments to be passed in, these are:

Argument nameDescription
firstShow the first [n] results, user defines [n].
lastShow the last [n] results, user defines [n].
beforePasses a cursor as a string and is combined with either the "first" or "last" argument to return the first/last [n] results before the given cursor.
afterPasses a cursor as a variable and is combined with either the "first" or "last" argument to return the first/last [n] results after the given cursor)
note

A filter by type query requires either the "First" or "Last" argument to be defined in order for the query to be valid. "First" and "Before" also can not be used together. Similarly, "Last" and "After" can not be used together.

Fields
Link copied!

Filter by content type queries support 2 different fields, these are:

Argument nameDescription
edgeThis field is used to specify which fields to return for each content item of that type. Further details of how to use this field are described below.
pageInfoThis field is used to return pagination information.

Edge
Link copied!

The edge field is used to specify which fields to return for each content item of that type. The "edge" field is made up of two further fields, see below:

Argument nameDescription
cursorThis field is used to return a cursor for each content item for the given content type.
nodeThis field is used to specify fields from the content item to return. This field contains all fields the corresponding single GraphQL type contains.

Page Info
Link copied!

The "pageInfo" field is used to return pagination information. The "pageInfo" field is made up of four further fields, see below:

Argument nameDescription
endCursorWhen specified returns the End Cursor for the results page.
hasPreviousPageWhen specified returns a Boolean response indicating if the current page has a previous page.
hasNextPageWhen specified returns a Boolean response indicating if the current page has a next page
startCursorWhen specified returns the Start Cursor for the results page.

Pagination
Link copied!

GraphQL filter uses the cursor connections specification to allow pagination of results. With pagination, a maximum of 50 results is returned for each page. You can specify the page size in the filter request. If you don't specify the page size, the maximum number of 50 items will be returned.

In the following example the page size is set to 1 using the first argument, which gives us our response in a descending manner. In this case, the first content item will be returned per page in the response.

query {
allExampleAuthor(first: 1) {
edges {
node {
name
}
}
}
}

Alternatively, if we wanted the last item from our content, we would use the last argument and set this to 1.

query {
allExampleAuthor(last: 1) {
edges {
node {
name
}
}
}
}

In the next example the page size is set to the first 3, so a maximum of 3 content items will be returned per page in the response.

query {
allExampleAuthor(first: 3) {
edges {
node {
name
}
}
}
}

Due to the maximum page size being 50, we cannot set the page size to more than this number. If we do, an error will be given that tells us the correct number of items that can be shown per page. In the screenshot below, we have set the page size to 100 using the first argument. In response, we have received an error informing us that the max page size is 50.

The maximum page size The maximum page size

If you would like to know whether your paginated content has a next or previous page, you would use the hasNextPage or hasPreviousPage argument, which would return a boolean result. For example, below we are checking to see whether our paginated list of author names would have a next page if we set the page size to 2.

{
allExampleAuthor(first: 2) {
pageInfo {
hasNextPage
}
}
}

This gives us the following result, which shows us that our content indeed does have another page of results for us to query for:


"data": {
"allExampleAuthor": {
"pageInfo": {
"hasNextPage": true
}
}
}
}

To query for the next page of content, we will need to fetch the endCursor and startCursor. An example of an endCursor query follows the below format:

{
allExampleAuthor(first: 2) {
pageInfo {
endCursor
}
}
}

This gives us the endCursor as a response:

{
"data": {
"allExampleAuthor": {
"pageInfo": {
"endCursor": "eyJzb3J0S2V5IjoiNjQyMzdlZGEyMDc3MmQwMDAxYTkwNDU3IiwiaXRlbUlkIjoiYW1wbGllbmNlLWV4YW1wbGVzOjdlZmNjMjkwLWMxYzEtNGRkYS05ZmU1LTU1ZGIzMTU2Y2VlNSJ9"
}
}
}
}

We can then use this endCursor string to query for last results of the next page of results. To do this we would include the endCursor string in our query while using the before argument:

{
allExampleAuthor(
before: "eyJzb3J0S2V5IjoiNjQyMzdlZGEyMDc3MmQwMDAxYTkwNDU3IiwiaXRlbUlkIjoiYW1wbGllbmNlLWV4YW1wbGVzOjdlZmNjMjkwLWMxYzEtNGRkYS05ZmU1LTU1ZGIzMTU2Y2VlNSJ9"
last: 1
) {
edges {
node {
name
}
}
}
}

Alternatively, we can include the startCursor string in our query while using the after argument to query for the first results, as shown below.

{
allExampleAuthor(
after: "eyJzb3J0S2V5IjoiNjQyMzdmOTAwMzE5ZGIwMDAxY2Q5NzdkIiwiaXRlbUlkIjoiYW1wbGllbmNlLWV4YW1wbGVzOjAyMGY1Y2I4LTIxOWYtNDI4MC04ZGQ2LTcyZjIwMjJhNGU3OSJ9"
first: 1
) {
edges {
node {
name
}
}
}
}

To get the startCursor, we would query for it in the same way we query for the endCursor.

For more information about pagination and limits, read the API limits page.

Listing content
Link copied!

If you want to list content for a given content type you can use the all[GraphQL name] typename. For example, if you have a content type schema called BlogPost, you would use the allBlogPost GraphQL typename to list all pieces of content for that Content Type. Alternatively, if you want to return a single piece of content by a specific delivery ID or Key, you would then query by BlogPost without the all prefix.

In the example shown below we are querying for the titles and descriptions of all content created by the blog content type schema. To do this we use the edge and node field within our query:

{
allBlogPostFilter(first: 3) {
edges {
node {
title
description
}
}
}
}

All blog titles and descriptions created using this schema will be returned in the response:

{
"data": {
"allBlogPostFilter": {
"edges": [
{
"node": {
"title": "Menswear recommendations",
"description": "Menswear picks for your spring wardrobe refresh"
}
},
{
"node": {
"title": "Indoor play ideas for the kids this half term",
"description": "Try out our ideas for indoor play and entertainment this week."
}
},
{
"node": {
"title": "Beauty picks for your new spring look",
"description": "Fancy some new products for the new season? Look no further, we've got you covered."
}
}
]
}
}
}

More list examples
Link copied!

These examples demonstrate how to use the first and last arguments when listing content in GraphQL. In this instance, we are listing the names of authors from the author content type.

Return first two names in list of author names from author type
Link copied!

{
allExampleAuthor(first: 2) {
edges {
node {
name
}
}
}
}

The above query gives us the following GraphQL response:

{
"data": {
"allExampleAuthor": {
"edges": [
{
"node": {
"name": "Kemi Elizabeth"
}
},
{
"node": {
"name": "Jon Lansdell"
}
}
]
}
}
}

Return last two items in list of author names from author type
Link copied!

query {
allExampleAuthor(last: 2) {
edges {
node {
name
}
}
}
}

The above query gives us the following GraphQL response:

{
"data": {
"allExampleAuthor": {
"edges": [
{
"node": {
"name": "Kemi Elizabeth Ojogbede"
}
},
{
"node": {
"name": "Helen Elizabeth Symington"
}
}
]
}
}
}

For more information on how the first and last arguments work, refer to Pagination.

Filtering content
Link copied!

You can filter on other string, number or boolean properties defined in your content type schema. For example, you could return all products with a category of "mens suits" or all blogs with the category of "homeware". Filters can be combined, so you can filter on products with a category of "ties" that are in the "Silk" product family, or all blogs in a particular category with a read time of 10.

The filterable trait
Link copied!

If you want to filter on any other properties then these properties must be defined in a trait:filterable object in the content type schema.

The trait includes a filterBy array that includes the path for each property that you will use to filter your content. Path entries are specified in JSON Pointer format and can be string, number or boolean types. The filterBy array can contain up to 5 paths, not including the schema id which is included automatically.

Before defining a path to be filtered on, a graphql:filtername must be given using standard camel case. This must be followed by the filterBy array which will be used to make a request to the filter API to retrieve content with properties of the specified value.

In the example we are using the category property as a filter.

"trait:filterable": {
"filterBy": [
{
"graphql:filtername": "byCategory",
"paths": ["/category"]
}
]
}

Note that you can only include properties defined in the schema itself and not in any linked content.

Filtering using multiple properties
Link copied!

Filters can be combined, so you could request all products that have a categoryId of "mens-accessories-ties" and a product family of "Silk". To combine filters you need to define a path containing both filters. In the example shown below the productFamily and categoryId properties are combined:

"trait:filterable": {
"filterBy": [
"graphql:filtername": "byProductFamilyAndCategory",
"paths": ["/productFamily", "/categoryId"]
}

Up to 5 entries can be included in a single path.

Specifying filter in your GraphQL query
Link copied!

To filter content using one of the paths defined in your filterBy array, include the schema, the graphql:filtername and the path in your GraphQL query. In the example shown below, we're requesting the categoryID and SKU numbers of all content created by the PDP content block content type that has a product family of "Womenswear". Note that you always need to include the schema in the request.

query {
allPdpContentBlock (
first: 3,
filter:{
byProductFamily:{
productFamily:"Womenswear"
}
})
{
edges {
node {
categoryId
sku
}
}
}
}

This query returns the following response:

{
"data": {
"allPdpContentBlock": {
"edges": [
{
"node": {
"categoryId": "grey-jacket",
"sku": "FR32450"
}
},
{
"node": {
"categoryId": "tailored-jacket",
"sku": "JSD451245"
}
}
]
}
}
}

If you want to query for content while filtering on multiple properties, you would need to first specify the paths you would like to filter on within the content type schema, and give that path a graphql:filtername.

For example, if we wanted to filter on both product family and category ID for a particular Pdp content block, we would first specify the paths in our content type schema and give it a graphql:filtername of byProductFamilyAndCategory, written in camel case. When querying for the content later, we would simply specify the graphql:filtername in our filter field and detail both the particular product family and category ID we're searching for.

The following code snippet shows what this query would look like if we were searching for the SKU id and meta info for all Pdp Content Blocks with the product family "Womenswear" and the category id "grey-jacket":

query {
allPdpContentBlock (
first: 3,
filter:{
byProductFamilyAndCategory:{
categoryId: "grey-jacket"
productFamily:"Womenswear"
}
})
{
edges {
node {
sku
_meta {
deliveryId
name
}
}
}
}
}

This query returns the following response:

{
"data": {
"allPdpContentBlock": {
"edges": [
{
"node": {
"sku": "FR32450",
"_meta": {
"deliveryId": "0341d22d-d7c9-49c5-9474-036c5b0ce243",
"name": "Womenswear product"
}
}
}
]
}
}
}

Sorting content
Link copied!

By default content will be returned sorted by date created, but you can specify your own sort order. For example, a list of blog posts could be sorted by read time or ranking.

To define a sort option you need to include a trait:sortable object in you content type schema containing the sort key, graphql:sortname and the path to one or more properties used to sort the content. It should be noted that if you choose to use a default sort key, you do not need to specify the graphql:sortname.

The sort trait
Link copied!

The trait:sortable object is added at the top level of the schema and can contain up to 3 sort paths, one of which must have the "default" key.

The trait includes a sortBy array that includes the path for each property that you will use to for your content. Path entries are specified in JSON pointer format and can be string, number or boolean types.

The trait:sortable object shown below includes a default sort key that is used to sort blog content using the readTime property. Due to this being the default sort key, we do not need to specify the graphql:sortname.

    "trait:sortable": {
"sortBy": [
{
"key": "default",
"paths": ["/readTime"]
},
]
}

You can specify multiple entries in a sort path, up to a maximum of 5.

In the example below we have specified two sort keys: "default" and "readTime".

The default sort key will sort the content by date and ranking. If the blog post date of two items is the same, then the ranking will be used as a tie breaker.

The "readTime" sort key will sort the content by readTime followed by date and then if those properties are both equal, "ranking" will be used.

The use of a graphql:sortname is encouraged, but if one is not included, there will be an attempt to infer the sort name from the key field. If the inferred name causes a naming collision with another sort name, it will prevent the generation of a schema. In this case, a unique graphql:sortname would have to be specified.

When creating a sort name, make sure to use standard camel case naming conventions - ie. byTime, byDate, byRanking.

note

Using a duplicate graphql:sortname or graphql:filtername will cause a schema to not be generated until the conflict is resolved by a unique graphql:sortname or graphql:filtername being specified.

"trait:sortable": {
"sortBy": [
{
"key": "default",
"paths": ["/date", "/ranking"]
},
{
"graphql:sortname": "byTime",
"key": "readTime",
"paths": ["/readTime", "/date", "/ranking"]
}
]
},

Specifying sort in your GraphQL query
Link copied!

If you have included a trait:sortable object in your content type schema, then if you don't specify a sort in your GraphQL filter query, the content will be sorted using your default sort and in ascending order.

To specify a sort, include a sortBy object in your query. In the example shown below, we're requesting the titles of all items created by our blog content type and sorted in descending order by readTime, followed by date and then ranking. If you don't specify a sort order, then ascending order will be used.

If you do not include a sort trait in your schema, the content will be sorted by date created.

{
allBlogPostFilter(first: 3, sortBy: { key: byTime, order: DESC }) {
edges {
node {
title
}
}
}
}

This gives us the following JSON format response:

{
"data": {
"allBlogPostFilter": {
"edges": [
{
"node": {
"title": "Beauty picks for your new spring look"
}
},
{
"node": {
"title": "Indoor play ideas for the kids this half term"
}
},
{
"node": {
"title": "Menswear recommendations"
}
}
]
}
}
}

Other notes
Link copied!

  • The default and maximum page size is 50.
  • The request timeout is 10 seconds. If this time is exceeded the request will return a 524 error
  • There is a complexity limit of 1000 items. This refers to the number of content items involved in processing a request. If the limit is exceeded, a 524 error is returned.
  • If you request filter paths that are not included in your content type schema then the request will not return an error and instead 0 items will be returned.

Example schemas
Link copied!

The example requests on this page use two schemas:

  • Blog post filter and sort. This is an update to the blog post schema used in our search examples. It has been modified to support filtering and sorting. It's included in the schema examples and also on its own page.

  • Product details. This is a product details schema that has multiple filterable properties. It's also included in the schema examples and also on its own page.

GraphQL overview

JSON pointer

Schema examples

Limits