Query documents by tag references with dynamic ordering in Sanity
The issue with your query is that you cannot pass the order expression itself as a parameter like order($orderBy). GROQ doesn't support dynamic ordering expressions through parameters in this way.
According to the order() function documentation, while you can pass document types and reference tags as parameters to GROQ queries, passing the order expression itself as a parameter (e.g., $orderBy containing "publishedAt desc") doesn't work as expected.
Solutions
Option 1: Construct Different Queries (Recommended)
Build separate queries based on your ordering needs:
// In your application code
const orderClause = ascending ? 'publishedAt asc' : 'publishedAt desc';
const query = ascending
? `*[_type in $documentTypes
&& count((tags[]->tag.current)[@ in $referenceTags]) > 0]
| order(publishedAt asc)
{
"type": _type,
publishedAt,
title,
"tags": tags[]->label
}`
: `*[_type in $documentTypes
&& count((tags[]->tag.current)[@ in $referenceTags]) > 0]
| order(publishedAt desc)
{
"type": _type,
publishedAt,
title,
"tags": tags[]->label
}`;
const results = await client.fetch(query, { documentTypes, referenceTags });Option 2: Sort Client-Side
Fetch the results without ordering and sort them in your application:
const query = `*[_type in $documentTypes
&& count((tags[]->tag.current)[@ in $referenceTags]) > 0]
{
"type": _type,
publishedAt,
title,
"tags": tags[]->label
}`;
const results = await client.fetch(query, { documentTypes, referenceTags });
// Sort in JavaScript
results.sort((a, b) => {
const dateA = new Date(a.publishedAt);
const dateB = new Date(b.publishedAt);
return ascending ? dateA - dateB : dateB - dateA;
});Option 3: Template Literal Approach
If you're comfortable with it, you can use template literals to construct the query dynamically:
const orderDirection = ascending ? 'asc' : 'desc';
const query = `*[_type in $documentTypes
&& count((tags[]->tag.current)[@ in $referenceTags]) > 0]
| order(publishedAt ${orderDirection})
{
"type": _type,
publishedAt,
title,
"tags": tags[]->label
}`;
const results = await client.fetch(query, { documentTypes, referenceTags });Option 1 or 3 is the most straightforward approach and maintains server-side sorting performance, which is especially important for larger datasets. Option 2 works well if you have a small result set or need more complex sorting logic that's easier to express in JavaScript.
Show original thread40 replies
Sanity â Build the way you think, not the way your CMS thinks
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.