How to set keys for the return of a query in Sanity.io
Unfortunately, GROQ doesn't support dynamic keys where you can use a field's value as the key name in the returned object. In your example, you're trying to return an object where each document is keyed by its navId.current value, but GROQ doesn't have this capability built-in.
What GROQ can do:
- You can create static key names in projections:
{"id": navId.current} - You can return arrays of objects:
*[_type == 'navigation']{...}
What GROQ cannot do:
- Use a field value as the object key name dynamically
- Return results as an object keyed by document properties (like
{ "nav-1": {...}, "nav-2": {...} })
Workarounds:
- Transform on the client side (recommended): Query for an array and transform it in your application code:
*[_type == 'navigation'] {
navId,
"id": navId.current,
items[]{ /* ... */ }
}Then in JavaScript:
const result = await client.fetch(query);
const keyed = result.reduce((acc, item) => {
acc[item.navId.current] = item;
return acc;
}, {});Use array format: Keep your data as an array and use array methods like
.find()when you need to access specific items by their navId.Custom GROQ functions: If you're on a plan that supports custom GROQ functions, you might be able to create a custom function for this transformation, though this is a more advanced approach.
The client-side transformation is the standard approach for this use case since it's simple, performant, and gives you the flexibility to structure your data however you need it in your application. This is a common pattern when working with GROQ - the query language is designed to return arrays of documents, and you handle reshaping into other data structures in your application code.
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.