Recursive queries
Describe how to use recursive queries in Optimizely Graph.
In content management systems (CMSs), content items are often linked or nested within one another. For example, a landing page might contain various content blocks, each containing other nested elements. Optimizely Graph provides mechanisms to traverse these relationships efficiently.
Self-recurring queries (@recursive
directive solution)
@recursive
directive solution)The @recursive
directive lets you recursively extend your query with the specified depth while traversing nested relationships. Using the GraphQL client to communicate Optimizely Graph is a limited but safer option.
The following example shows the recursive directive:
query recursiveQuery {
_Content(limit: 100, where: { _metadata: { types: { eq: "StartPage" } } }) {
items {
... on StartPage {
TestAreas {
...LandingPage
}
}
}
}
}
fragment LandingPage on _IContent {
_metadata {
displayName
types
}
... on GroupCardListBlock {
GroupedItemContentArea @recursive(depth: 10)
}
... on LandingPage {
TopContentArea @recursive(depth: 2)
MainContentArea @recursive
}
}
Explanation
- Entry Point – The query starts by fetching
StartPage
content items. TheTestAreas
is typed of ContentArea to contain nested content items. - Fragment – The
LandingPage
fragment defines the data structure you want to retrieve from each content item.
@recursive
directive
-
GroupedItemContentArea @recursive(depth: 10)
– This instructs Optimizely GraphQL to fetch nested content within GroupedItemContentArea up to a depth of ten levels. The allowed depth is between one and ten.-
TopContentArea @recursive(depth: 2)
– Similar to the above, but limited to two levels of nesting. -
MainContentArea @recursive
– This has no specified depth, meaning it will fetch all nested content within MainContentArea by one level (this is the default value). -
The
@recursive
directive must be applied to a field that returns the same type as its associated fragment. For example, content areas likeGroupedItemContentArea
,TopContentArea
, andMainContentArea
are suitable for the@recursive
directive because they all return _IContent. You can verify this by checking theDocumentation Explorer
on GraphiQL.
-
Key Points
- Flexibility – You can control the recursion depth for different fields.
- Efficiency – Recursive queries can be more efficient than multiple round trips to fetch nested data.
- Cycle Prevention – The depth argument prevents infinite loops.
Circular-referenced queries (cyclic fragments)
Circular-referenced queries are a much more natural way to retrieve data for the nested blocks. You can reuse the fragment definitions as either self (A -> A) or cross (A -> B -> C -> A) referenced way to retrieve the nested data.
The following example shows a cyclic query:
query cyclicQuery {
_Content(limit: 100, where: { _metadata: { types: { eq: "StartPage" } } }) {
items {
... on StartPage {
TestAreas {
...LandingPage
}
}
}
}
}
fragment LandingPage on _IContent {
_metadata {
displayName
types
}
... on GroupCardListBlock {
GroupedItemContentArea {
...LandingPage
}
}
... on LandingPage {
TopContentArea {
...LandingPage
}
MainContentArea {
...LandingPage
}
}
}
Explanation
- This query and fragment are identical to the recursive query.
- The difference is that the
LandingPage
fragment reference in the query does not have any depth info, so it might be infinitely deep in theory. But it is not because it depends on the indexed data, which has ten levels of depth. - The lines of
...LandingPage
must be placed under the fields that are in the same data type with its associated fragment, which is_IContent
in this case. Here, it is correctly placed insideGroupedItemContentArea
,TopContentArea
, andMainContentArea
, all of which return_IContent
, similar to the placement requirements for the@recursive directive
.
Important Considerations
Performance – Be mindful of the performance implications, especially when dealing with deeply nested content.
Compliance – Although using a cyclic query is a much easier and more flexible method, it may not be compatible with your GraphQL client.
Updated 2 months ago