GraphQL queries
GraphQL lets you create queries in both long-form and short formats.
By default, a GraphQL query only returns the first ten results found. To change this, use the first
argument. See the GraphQL examples for the structure and implementation of GraphQL queries in Sitecore Content Hub.
Search for an asset by ID
The following query fetches data about a single asset from the M_Asset entity type with a specific ID (asset.alexander-mils-667996
).
{
m_Asset(id: "asset.alexander-mils-667996") {
fileName
title
createdOn
}
}
The results are as follows:
{
"data": {
"m_Asset": {
"fileName": "alexander-mils-667996.jpg",
"title": "Elderflower cordial",
"createdOn": "2022-11-03T04:27:34.000Z"
}
}
}
Search by definition
The following query fetches data from the M_Content entity type and returns the id
and content_Name
for each entity.
{
allM_Content {
results {
id
content_Name
}
}
}
The results are as follows:
{
"data": {
"allM_Content": {
"results": [
{
"id": "tTMVYivL2UyM3300lnraRQ",
"content_Name": "Fruitful Summer (gb)"
},
{
"id": "LB0MQmR3U0ST9NX2V4L_vA",
"content_Name": "Fruitful Summer (es)"
},
{
"id": "TmYSxnfrqUWL1-1VEL-ZdA",
"content_Name": "Fruitful Summer (us)"
},
{
"id": "Content.PowerofProtein",
"content_Name": "The Power of Protein"
},
{
"id": "Content.Snacking",
"content_Name": "Snacking"
},
{
"id": "Content.SalsaWithFruitChips",
"content_Name": "Flavorful's famous salsa with Healthful fruit chips"
}
]
}
}
}
Resolve types from interfaces
Interface
is an abstract type that includes a certain set of fields that a type must include to implement the interface. It is only available for the ContentTypes entities defined in Content Hub.
The following query fetches entities from M.Content that have names containing Fruitful Email, Fruitful Blog, or Healthy Mimosa:
query contentEmailBlogInterface {
allM_Content(
where: {
OR: [
{ content_Name_contains: "Fruitful Email" }
{ content_Name_contains: "Fruitful Blog" }
{ content_Name_contains: "Healthy Mimosa" }
]
}
) {
total
results {
content_Name
... on M_Content_Blog {
blog_Title
blog_Body
}
... on M_Content_Email {
email_Subject
email_Body
}
}
}
}
The results are as follows:
{
"data": {
"allM_Content": {
"total": 5,
"results": [
{
"content_Name": "Fruitful Blog",
"blog_Title": "Fruitful juices",
"blog_Body": " figure class=\"image\" img width=\"150\" alt=\"Fruitful logo (black)\" src=\"https://stylelabsdemo.com/api/public/content/363909544a354d3b9a4549c306c88bbe?v=ad464f64\" /figure p br /p p i strong Un tonto se cree sabio, pero un hombre sabio sabe que es un tonto. /strong /i /p figure class=\"image\" img width=\"200\" alt=\"Fruitful Orange mocktail\" src=\"https://stylelabsdemo.com/api/public/content/0268acbebdb643aa83d918ff8d03283d?v=f3607a38\" /figure p style=\"text-align:center;\" /p p style=\"text-align:center;\" /p p i strong Más valen tres horas adelantadas que un minuto tarde. /strong /i /p "
},
{
"content_Name": "Fruitful Email (es-ES)",
"email_Subject": "Fruitful juices",
"email_Body": " figure class=\"image\" img width=\"150\" alt=\"Fruitful logo (inverted)\" src=\"https://stylelabsdemo.com/api/public/content/5b2a9683096b4543b997346c15bda790?v=b426739c\" /figure p i strong Los cobardes mueren muchas veces antes de su muerte; los valientes nunca sienten la muerte sino sólo una vez /strong /i /p figure class=\"image\" img width=\"380\" alt=\"Lime mocktail with lime slice\" src=\"https://stylelabsdemo.com/api/public/content/99c986d065aa45fda3a692e0e27d3928?v=45b06955\" /figure p i strong El infierno está vacío y todos los demonios están aquí. /strong /i /p "
},
{
"content_Name": "Fruitful Email",
"email_Subject": "Fruitful juices",
"email_Body": " figure class=\"image\" img width=\"150\" src=\"https://stylelabsdemo.com/api/public/content/5b2a9683096b4543b997346c15bda790?v=b426739c\" alt=\"Fruitful logo (inverted)\" /figure p Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque non ipsum mattis, elementum velit maximus, mattis eros. /p figure class=\"image\" img srcset=\"https://stylelabsdemo.com/api/public/content/99c986d065aa45fda3a692e0e27d3928?v=45b06955&t=w320 320w\" width=\"380\" src=\"https://stylelabsdemo.com/api/public/content/99c986d065aa45fda3a692e0e27d3928?v=45b06955\" alt=\"Lime mocktail with lime slice\" /figure p Etiam cursus viverra ante eu faucibus. Ut porttitor. /p p /p "
},
{
"content_Name": "Fruitful Blog",
"blog_Title": "Fruitful juices",
"blog_Body": " figure class=\"image\" img width=\"150\" src=\"https://stylelabsdemo.com/api/public/content/363909544a354d3b9a4549c306c88bbe?v=ad464f64\" alt=\"Fruitful logo (black)\" /figure p br /p p Lorem ipsum dolor sit amet, consectetur adipiscing elit. /p figure class=\"image\" img width=\"200\" src=\"https://stylelabsdemo.com/api/public/content/0268acbebdb643aa83d918ff8d03283d?v=f3607a38\" alt=\"Fruitful Orange mocktail\" /figure p style=\"text-align:center;\" /p p style=\"text-align:center;\" /p p /p "
},
{
"content_Name": "Healthy Mimosa blog",
"blog_Title": "Who wants a mimosa?!",
"blog_Body": " p I do, always! Mimosas are supremely simple bubbly cocktails made with sparkling wine and orange juice. They're light, fizzy and easy to sip. /p p I love ordering mimosas at weekend brunch, and serving them to family and friends on holidays—Easter, Mother's Day, July 4th, Christmas, you name it. Mimosas liven up wedding showers and baby showers. I bring mimosa supplies to football watch parties, and no one complains. I've shared a few variations on mimosas over the years. Today, I'm going to share everything you've ever wanted to know about mimosas, plus a basic mimosa recipe and variations. If you haven't poured your first mimosa yet, you'll be a mimosa expert by the end of this post! If you're a seasoned mimosa drinker, I think you'll find some new tips here, too. /p p /p p span class=\\\"text-big\\\" strong Mimosa Ingredients: /strong /span /p p Classic mimosas require just two ingredients: dry sparkling wine, and orange juice. Some recipes will tell you to add some other alcohol or orange liqueur. Don't listen to them! /p p strong Sparkling Wine /strong /p p The best Champagne for mimosas isn't actually Champagne. For mimosas, opt for less-expensive Cava or Prosecco. Cava is from Spain and Prosecco is from Italy, but they're both delicious dry sparkling wines that mix well with juice. Bonus? They're affordable. A good bottle of Cava or Prosecco will run about $12 to $16. Avoid super cheap sparkling wine, unless you want a headache with your mimosas. Don't waste your pricy bottle of Champagne on mimosas, since we're diluting those delicate notes with orange juice. /p p strong Orange Juice /strong /p p Cold, fresh orange juice is best for mimosas. If you're buying orange juice at the store, opt for high-quality such as the Fruitful Orange Juice! /p p strong Mimosa Ratio /strong /p p The perfect ratio of sparkling wine to orange juice is up to you. My suggestion? Start with the 50/50 ratio suggested below and adjust from there. I make my mimosas with 2 parts sparkling wine and 1 part orange juice—they're light, fizzy, and pack a punch. That's how we made them when I was a bartender. If you like sweeter, more juicy mimosas, start with a 50/50 ratio and add more orange juice if desired. After some delicious experimentation, you'll know exactly how you like your mimosas! /p "
}
]
}
}
}
These results include the content name field, the blog title and body fields from the virtual M_Content_Blog type, and the email subject and body fields from the virtual M-Content_Email type. You can request such inclusions by prepending the type with ... on [Type]
in the query, creating a qualifier for the content type when an interface is returned.
Total
The total
field returns the number of entities that match specified criteria.
There are no criteria specified in the following example, so the query returns the total number of entities in M.Content:
{
allM_Content {
total
}
}
The results show a total of 23 entities:
{
"data": {
"allM_Content": {
"total": 23
}
}
}
Where
Adding a where
clause to a query lets you restrict the number of results according to custom criteria, which can include logical operators such as AND
and OR
, and postfixes such as:
-
_eq
-
_neq
-
contains
-
fulltext
Equal to
The following example includes a where
clause stating that the asset title
must be equal to a specific phrase:
query AssetTitle {
allM_Asset(where: { title_eq: "Group selfie with drinks" }) {
total
results {
fileName
title
fileSize
isDraft
}
}
}
The results are as follows:
{
"data": {
"allM_Asset": {
"total": 1,
"results": [
{
"fileName": "videoblock-example3.mp4",
"title": "Group selfie with drinks",
"fileSize": 10.08,
"isDraft": null
}
]
}
}
}
Not equal to
The following example includes a where
clause specifying that the asset isDraft
property must have a value that is not null
:
query AssetDraftIsNotNull {
allM_Asset(where: { isDraft_neq: null }) {
total
results {
fileName
fileSize
isDraft
}
}
}
The results are as follows:
{
"data": {
"allM_Asset": {
"total": 1,
"results": [
{
"fileName": "videoblock-example3.mp4",
"fileSize": 10.08,
"isDraft": true
}
]
}
}
}
Contains
Use the contains
postfix to search for a phrase inside a given field. This postfix only works on a single field.
The following example includes a where
clause specifying that the content_Name
property must contain the term Fruitful:
{
allM_Content(where: { content_Name_contains: "Fruitful" }) {
total
results {
content_Name
m_Content_IsVariant
}
}
}
The results are as follows:
{
"data": {
"allM_Content": {
"total": 7,
"results": [
{
"content_Name": "Sparkling Punch using Fruitful Orange",
"m_Content_IsVariant": null
},
{
"content_Name": "Fruitful Summer (us)",
"m_Content_IsVariant": true
},
{
"content_Name": "Fruitful Summer (gb)",
"m_Content_IsVariant": true
},
{
"content_Name": "Fruitful Summer (es)",
"m_Content_IsVariant": null
},
{
"content_Name": "Fruitful refreshing ginger lemonade",
"m_Content_IsVariant": null
},
{
"content_Name": "Fruitful Cocktails",
"m_Content_IsVariant": null
},
{
"content_Name": "Fruitful Mocktails",
"m_Content_IsVariant": null
}
]
}
}
}
Operators
There are other operators you can use with the contains
postfix such as:
-
[fieldname]_in
- checks for values that appear in a defined list of potential values. -
[fieldname]_startswith
checks for values that start with a specific string. -
[fieldname]_endswith
checks for values that end with a specific string.
For a complete list, in the GraphQL IDE, click the Schema tab.
Most operators include an inverted version, which looks for values that do not match the specified criteria. For example, [fieldname]_not_contains
is the opposite of [fieldname]_contains
.
Full-text search
Use fulltext
in the where
clause to perform a full-text search. Unlike the contains
postfix, fulltext
searches all fields of the relevant entity, as well as any applicable relations to ancestors marked for full-text search, for a specific word or a phrase. The fields searched are those that are configured in Content Hub as full text properties.
The following example queries M.Asset for the phrase fruitful lemon in any searchable field:
query {
allM_Asset(where: {
fulltext: "fruitful lemon"
}) {
results {
title
}
}
}
The results are as follows:
{
"data": {
"allM_Asset": {
"results": [
{
"title": "Fruitful Lemon mocktail with dried lemon slices-9926"
},
{
"title": "Fruitful Lemon mocktail with dried lemon slices-9837"
},
{
"title": "Fruitful Lemon mocktail with dried lemon slices-9748"
},
{
"title": "Fruitful Lemon mocktail with dried lemon slices-9659"
},
{
"title": "Fruitful Lemon mocktail with dried lemon slices-9570"
},
{
"title": "Fruitful Lemon mocktail with dried lemon slices-9481"
},
{
"title": "Fruitful Lemon mocktail with dried lemon slices-9392"
},
{
"title": "Fruitful Lemon mocktail with dried lemon slices-9303"
},
{
"title": "Fruitful Lemon mocktail with dried lemon slices-9214"
},
{
"title": "Fruitful Lemon mocktail with dried lemon slices-9125"
}
]
}
}
}
You can combine fulltext
with other postfixes, for example:
query {
allM_Asset(where: {
fulltext: "Fruitful Lemon mocktail with dried lemon slices"
title_contains: "92"
}) {
results {
title
}
}
}
The results are as follows:
{
"data": {
"allM_Asset": {
"results": [
{
"title": "Fruitful Lemon mocktail with dried lemon slices-9926"
},
{
"title": "Fruitful Lemon mocktail with dried lemon slices-9392"
},
{
"title": "Fruitful Lemon mocktail with dried lemon slices-9214"
},
{
"title": "Fruitful Lemon mocktail with dried lemon slices-5921"
},
{
"title": "Fruitful Lemon mocktail with dried lemon slices-492"
}
]
}
}
}
Order by
Use the orderBy
keyword to sort the result set in a specific order.
The following query sorts results by the recipe title. You can append _DESC
or _ASC
to specify the sort order as descending or ascending.
{
allM_Content_Recipe(
where: { recipe_Title_contains: "Fruitful" }
orderBy: RECIPE_TITLE_ASC
) {
total
results {
recipe_Title
}
}
}
The results are as follows:
{
"data": {
"allM_Content_Recipe": {
"total": 4,
"results": [
{
"recipe_Title": "Fruitful mango mocktail"
},
{
"recipe_Title": "Fruitful refreshing ginger lemonade as an alternative to soda"
},
{
"recipe_Title": "Fruitful's famous salsa with Healthful fruit chips"
},
{
"recipe_Title": "Sparkling Punch using Fruitful Orange"
}
]
}
}
}
Logical operators
You can use AND
and OR
logical operators to combine statements, creating advanced logic in your queries.
AND
The AND
operator is used to combine two statements. For a given entity to be returned by the query, both statements must be true for that entity.
The following query returns results from M.Content where the content name contains Healthy Mimosa and the the blog quote is Who wants a mimosa:
{
allM_Content(
where: {
AND: [
{ content_Name_contains: "Healthy Mimosa" }
{ blog_Quote_neq: "Who wants a mimosa" }
]
}
) {
total
results {
content_Name
}
}
}
The results are as follows:
{
"data": {
"allM_Content": {
"total": 1,
"results": [
{
"content_Name": "Healthy Mimosa blog"
}
]
}
}
}
OR
The OR
operator is used to combine two statements. For a given entity to be returned by the query, at least one of the statements much be true for that entity.
The following query returns content where the content name is either The Power of Protein or Healthy Mimosa.
{
allM_Content(
where: {
OR: [
{ content_Name_contains: "The Power of Protein" }
{ content_Name_contains: "Healthy Mimosa" }
]
}
) {
total
results {
content_Name
}
}
}
The results are as follows:
{
"data": {
"allM_Content": {
"total": 2,
"results": [
{
"content_Name": "The Power of Protein"
},
{
"content_Name": "Healthy Mimosa blog"
}
]
}
}
}
AND with nested OR
You can nest the AND
and OR
operators.
The following query searches for content with the name summer savings or Fruitful refreshing ginger lemonade.
{
allM_Content(
where: {
AND: [
{
OR: [
{ content_Name_eq: "Summer Savings" }
{ content_Name_eq: "Fruitful refreshing ginger lemonade" }
]
}
{ m_Content_IsVariant_eq: false }
]
}
) {
total
results {
content_Name
m_Content_IsVariant
createdOn
}
}
}
The results are as follows:
{
"data": {
"allM_Content": {
"total": 3,
"results": [
{
"content_Name": "Summer Savings",
"m_Content_IsVariant": false,
"createdOn": "2021-07-29T13:56:32.000Z"
},
{
"content_Name": "Summer Savings",
"m_Content_IsVariant": false,
"createdOn": "2021-07-29T13:55:39.000Z"
},
{
"content_Name": "Fruitful refreshing ginger lemonade",
"m_Content_IsVariant": false,
"createdOn": "2021-07-29T12:17:38.000Z"
}
]
}
}
}
Typename
The __typename
field contains the name of the GraphQL schema type for that object. For example:
query typeName {
allM_Content(where: {content_Name_contains: "Mimosa"}) {
total
results{
content_Name
__typename
}
}
}
Running multiple queries
You can run multiple queries in a single request. The queries do not impact each other. In the following example, there are two queries running at the same time:
-
The first query (
Blog
) searches M.Content, using the virtual blog types, for blogs that have Fruitful in the title and have a body that is not null. It orders the results by blog title, in ascending order. -
The second query (
Email
) searches M.Content, using the virtual email types, for emails that have Fruitful in the title and have a body is not null. It orders the results by email type, in ascending order.
query contentEmailBlog {
allM_Content_Blog(
where: { blog_Title_contains: "Fruitful", blog_Body_neq: null }
orderBy: BLOG_TITLE_ASC
) {
total
results {
blog_Title
blog_Body
blog_Quote
}
}
allM_Content_Email(
where: { email_Subject_contains: "Fruitful", email_Body_neq: null }
orderBy: EMAIL_SUBJECT_ASC
) {
total
results {
email_Subject
email_Body
}
}
}
The results of these two queries, which are grouped within a single object named data, are as follows:
{
"data": {
"blog": {
"total": 3,
"results": [
{
"blog_Title": "Fruitful blog",
"blog_Body": " p There is no one who loves pain itself, who seeks after it and wants to have it, simply because it is pain. There is no one who loves pain itself, who seeks after it and wants to have it, simply because it is pain. There is no one who loves pain itself, who seeks after it and wants to have it, simply because it is pain /p figure class=\"image\" img width=\"1100\" alt=\"Refreshing mocktails\" src=\"https://stylelabsdemo.com/api/public/content/2ed85585609c43bda24ae92372a5f311?v=f4d87d58\" /figure ",
"blog_Quote": " p The strong fruit /strong of your own hard work is the sweetest. /p "
},
{
"blog_Title": "Fruitful blog",
"blog_Body": " p Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi pulvinar tellus non augue vestibulum vulputate. Proin non tortor vitae ante tincidunt dictum eget vitae tortor. /p figure class=\"image\" img width=\"1100\" alt=\"Refreshing mocktails\" src=\"https://stylelabsdemo.com/api/public/content/2ed85585609c43bda24ae92372a5f311?v=f4d87d58\" /figure ",
"blog_Quote": " p br Le fruit de votre propre travail acharné est le plus doux. /p "
},
{
"blog_Title": "Fruitful blog",
"blog_Body": " p Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi pulvinar tellus non augue vestibulum vulputate. Proin non tortor vitae ante tincidunt dictum eget vitae tortor. /p figure class=\"image\" img width=\"1100\" alt=\"Refreshing mocktails\" src=\"https://stylelabsdemo.com/api/public/content/2ed85585609c43bda24ae92372a5f311?v=f4d87d58\" /figure ",
"blog_Quote": " p br El fruto de tu propio trabajo duro es el más dulce. /p "
}
]
},
"email": {
"total": 1,
"results": [
{
"email_Subject": "Fruitful Late Summer Email",
"email_Body": " p br strong Fruitful: /strong /p p No hay nadie que ame el dolor mismo, que lo busque y quiera tenerlo, simplemente porque es dolor. /p figure class=\"image\" img width=\"1100\" alt=\"Product layer 3\" src=\"https://stylelabsdemo.com/api/public/content/c8cc3c37df854f9c92c0ddef0795198d?v=0039f433\" /figure "
}
]
}
}
}
Cursor-based pagination
Cursor-based pagination returns a pointer to a specific item in the dataset. On subsequent requests, the server returns results after the given pointer.
First
The first
argument limits the number of results returned by the query. The value of this argument must be less than 1,000. The default value is 10. In the following example, the limit is two results.
query firstTwo {
allM_Content(first:2) {
total
results {
id
content_Name
m_Content_IsVariant
}
}
}
Without the first
argument, this query returns 28 entries. With the first
argument set to 2, the results include only the first two entities found:
{
"data": {
"allM_Content": {
"total": 28,
"results": [
{
"id": "BDolxU3bGkWMwFJk-s8Idg",
"content_Name": "Fruitful Summer (es-ES)",
"m_Content_IsVariant": true
},
{
"id": "igADXjecyk2oF4lo_tfs2Q",
"content_Name": "Fruitful Summer (es-ES)",
"m_Content_IsVariant": true
}
]
}
}
}
pageInfo
The pageInfo
type contains information needed for pagination.
endCursor
The endCursor
field represents the cursor associated with the last entity of the current page.
The cursor is opaque and not intended to be manipulated by the client.
query endCursor {
allM_Content(first: 5) {
total
results {
id
content_Name
m_Content_IsVariant
}
pageInfo {
endCursor
hasNext
}
}
}
The results are as follows:
{
"data": {
"allM_Content": {
"total": 28,
"results": [
{
"id": "BDolxU3bGkWMwFJk-s8Idg",
"content_Name": "Fruitful Summer (es-ES)",
"m_Content_IsVariant": true
},
{
"id": "igADXjecyk2oF4lo_tfs2Q",
"content_Name": "Fruitful Summer (es-ES)",
"m_Content_IsVariant": true
},
{
"id": "p70lTBrPSkqTZ2Ky3BdmWw",
"content_Name": "Fruitful Summer (es-ES)",
"m_Content_IsVariant": true
},
{
"id": "9zjJfWK_UkSoX8Gd1I8dPg",
"content_Name": "Fruitful Summer",
"m_Content_IsVariant": null
},
{
"id": "OwuHPqtSNk25OF6CPz6s8A",
"content_Name": "Fruitful Juices",
"m_Content_IsVariant": null
}
],
"pageInfo": {
"endCursor": "eyJzZWFyY2hBZnRlciI6WyIxNjEzNzMyMDk1MTcyIl0sImNvdW50Ijo1fQ==",
"hasNext": true
}
}
}
}
hasNext
hasNext
is a Boolean value indicating whether there are more results available:
query hasNext {
allM_Content(first: 2) {
total
results {
id
content_Name
m_Content_IsVariant
}
pageInfo {
hasNext
}
}
}
The results are as follows:
{
"data": {
"allM_Content": {
"total": 28,
"results": [
{
"id": "BDolxU3bGkWMwFJk-s8Idg",
"content_Name": "Fruitful Summer (es-ES)",
"m_Content_IsVariant": true
},
{
"id": "igADXjecyk2oF4lo_tfs2Q",
"content_Name": "Fruitful Summer (es-ES)",
"m_Content_IsVariant": true
}
],
"pageInfo": {
"hasNext": true
}
}
}
}
hasNext
is true
, so there are more results that were not returned.
After
The after
parameter lets you return only results that occur after a specific point in the overall dataset. This point is determined using a cursor, which can be obtained using a query containing the endCursor
argument. In the following query, pagination starts after the content item eyJzZWFyY2hBZnRlciI6WyIxNjEzNzMyMDk1MTcyIl0sImNvdW50Ijo1fQ==
.
query afterEndCursor {
allM_Content(
first: 5
after: "eyJzZWFyY2hBZnRlciI6WyIxNjEzNzMyMDk1MTcyIl0sImNvdW50Ijo1fQ=="
) {
total
results {
id
content_Name
m_Content_IsVariant
}
pageInfo {
endCursor
hasNext
}
}
}
The results are as follows:
{
"data": {
"allM_Content": {
"total": 28,
"results": [
{
"id": "wT5RNeIcQ0SHTORNT1faug",
"content_Name": "Fruitful Summer (it-IT)",
"m_Content_IsVariant": true
},
{
"id": "Content.SalsaWithFruitChips",
"content_Name": "Flavorful's famous salsa with Healthful fruit chips",
"m_Content_IsVariant": null
},
{
"id": "Content.PowerofProtein",
"content_Name": "The Power of Protein",
"m_Content_IsVariant": null
},
{
"id": "Content.PowerFromWithin",
"content_Name": "Power comes from within",
"m_Content_IsVariant": null
},
{
"id": "Content.FruitfulGinger",
"content_Name": "Fruitful refreshing ginger lemonade",
"m_Content_IsVariant": null
}
],
"pageInfo": {
"endCursor": "eyJzZWFyY2hBZnRlciI6WyIxNjEzMzY0Nzg0MTk4Il0sImNvdW50IjoxMH0=",
"hasNext": true
}
}
}
}