Issue with dynamically generated values in array filter in Slack thread.

3 replies
Last updated: Jan 31, 2024
Hello!
Do you know why
test
and
test1
works but not
test2
nor
test3
?
    "test": override_en_gb,
    "test1": @["override_en_gb"],
    "test2": @["override_"+$lang],
    "test3": @[string("override_"+$lang)],
AI Update

Looking at your GROQ query examples, the issue is about dynamic attribute access using variables with the @ operator (which refers to the current scope).

Here's what's happening:

Working examples:

  • "test": override_en_gb - Direct attribute access works
  • "test1": @["override_en_gb"] - Bracket notation with a literal string works

Not working:

  • "test2": @["override_"+$lang] - String concatenation inside bracket notation doesn't work
  • "test3": @[string("override_"+$lang)] - Even explicit string conversion doesn't work

The Problem

GROQ's bracket notation for attribute access (@[...]) expects a string literal or a direct variable reference, not a computed/concatenated expression. The expression inside the brackets is not evaluated as a dynamic key lookup in the way you might expect from JavaScript.

Solutions

Option 1: Use select() for conditional attribute access

*[]{
  "test": select(
    $lang == "en_gb" => @.override_en_gb,
    $lang == "fr" => @.override_fr,
    $lang == "de" => @.override_de
  )
}

This is the most GROQ-native approach - you explicitly handle each language case.

Option 2: Pre-compute the field name and use a parameter

If you're using a JavaScript client, compute the field name before passing it to GROQ:

const lang = "en_gb";
const fieldName = `override_${lang}`;

const query = `*[]{ "test": @[$fieldName] }`;
const result = await client.fetch(query, { fieldName });

Option 3: Return the entire object and process client-side

*[]{ ... }

Then in your application code:

const result = await client.fetch(query);
const processed = result.map(doc => ({
  ...doc,
  test: doc[`override_${lang}`]
}));

The fundamental limitation is that GROQ doesn't support dynamic string concatenation for property access paths. The bracket notation @[...] is meant for accessing properties with special characters or when the property name is stored in a variable, but that variable must contain the complete property name as a string value - not a concatenated expression.

If you need truly dynamic field access based on runtime values, Option 1 (select()) is your best bet for keeping the logic in GROQ, or Option 2/3 for handling it in your application code.

It’s not possible to filter on dynamically generated values like
"something" + $parameter
Just to clarify
test2
and
test3
are interpreted as an array filter and not an object key lookup. Would be nice if this worked better.
I see! It makes sense now! Thanks!

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.

Was this answer helpful?