Filter expanded references by properties in Sanity GROQ query

1 replies
Last updated: Mar 25, 2021
Does anyone know how to filter from properties of expanded references? For instance, I can get all recipes that have a
publishDate
earlier than the current time:

*[
  _type == "recipeArticle"
  && (!defined(releaseDate) || releaseDate <= $currentDate)
] | order(coalesce(releaseDate, _createdAt) desc) {
    title,
    otherRecipeFields
  }[$first..$last]
But I can't figure out how to filter by that
releaseDate
when these articles are references:

  *[_id == "allRecipesPage"]{
    editorsPicks {
      recipes[!defined(releaseDate) || releaseDate <= $currentDate]->{
        ${recipeTeaserGroq}
      },
    },
  }
That filter doesn't work, because it's only looking at the
ref
objects, which of course do not have their own
releaseDate
AI Update

Looking at your query, the issue is that you're trying to filter on the reference objects themselves before dereferencing them. In GROQ, you need to filter after dereferencing to access the properties of the referenced documents.

Here are a few approaches to solve this:

*[_id == "allRecipesPage"]{
  editorsPicks {
    "recipes": recipes[]-> {
      ${recipeTeaserGroq}
    }[!defined(releaseDate) || releaseDate <= $currentDate],
  },
}

The key is moving the filter to after the -> dereference operator. This way you're filtering on the actual recipe documents, not the reference objects.

Option 2: Filter inline during dereferencing

*[_id == "allRecipesPage"]{
  editorsPicks {
    "recipes": recipes[]->{
      ${recipeTeaserGroq}
    }[!defined(releaseDate) || releaseDate <= $currentDate],
  },
}

This is essentially the same as Option 1 - the filter [!defined(releaseDate) || releaseDate <= $currentDate] is applied to the dereferenced results.

Option 3: Use a subquery approach

*[_id == "allRecipesPage"]{
  editorsPicks {
    "recipes": recipes[]._ref in *[
      _type == "recipeArticle" 
      && (!defined(releaseDate) || releaseDate <= $currentDate)
    ]._id => recipes[]->{
      ${recipeTeaserGroq}
    },
  },
}

Option 1 or 2 are the cleanest approaches - just dereference first with ->, then apply your filter to the dereferenced documents. The filter sees the full recipe document properties after the dereference happens.

The pattern is: array[]->{projection}[filter] where the filter operates on the dereferenced documents, not on the reference objects themselves. This is documented in the Query Cheat Sheet under the "Joins" and "Object Projections" sections.

Show original thread
1 reply
Nevermind, figured it out:

  *[_id == "allRecipesPage"]{
    editorsPicks {
      recipes[]->[
         !defined(releaseDate) ||
         releaseDate <= $currentDate
      ]{
        ${recipeTeaserGroq}
      },
    },
  }

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?