
Grab your gear: The official Sanity swag store
Read Grab your gear: The official Sanity swag storeLooking at your query, yes, it can definitely be written in a more generic way! Your current approach hardcodes the depth (3 levels) and array indices. Here are several approaches to make it more flexible:
GROQ doesn't support recursive traversal of parent references at arbitrary depth. You can't write something like parent->parent->... dynamically. However, there are some practical solutions depending on your use case:
If you know the slug path structure, you can work with the array more flexibly:
*[
slug.current == $slug[-1] &&
parentPage->slug.current == $slug[-2] &&
parentPage->parentPage->slug.current == $slug[-3]
]This uses negative indexing to access elements from the end of the array, making it slightly more readable.
If your documents have a computed path field or you can build one, you could do:
*[
path == "/" + array::join($slug[1..], "/")
]This assumes you have a path field that stores the full hierarchical path.
For truly dynamic depth traversal, you could create a custom GROQ function (requires Growth plan or higher). This would allow you to define reusable logic for traversing parent chains.
The most practical solution for deep hierarchies is to denormalize by storing an ancestors array on each document:
{
slug: "page",
ancestors: [
{ _ref: "root-id" },
{ _ref: "parent-id" }
]
}Then your query becomes much simpler and works at any depth:
*[
slug.current == $slug[-1] &&
count(ancestors[@._ref in $ancestorIds]) == count($ancestorIds)
]Unfortunately, GROQ does not support arbitrary-depth recursive parent traversal. The language is intentionally designed without recursion to maintain performance and predictability. As explained in the How Queries Work documentation, your current approach of explicitly chaining parent->parent-> is actually the standard pattern when you know the depth.
If you need to support variable depths, denormalizing with an ancestors array is the recommended Sanity pattern. This also significantly improves query performance for deep hierarchies since you avoid multiple reference lookups.
Would you like help implementing the ancestors approach? It typically involves adding a field to your schema and using a migration or document action to populate it when documents are created or updated.
Sanity is the developer-first content operating system that gives you complete control. Schema-as-code, GROQ queries, and real-time APIs mean no more workarounds or waiting for deployments. Free to start, scale as you grow.
Content operations
Content backend


The only platform powering content operations
By Industry


Tecovas strengthens their customer connections
Build and Share

Grab your gear: The official Sanity swag store
Read Grab your gear: The official Sanity swag store