Filter Sanity products by field values (checkbox/array) not documents

4 replies
Last updated: Jul 18, 2021
I am trying to filter products by a certain value of a field, which is not a document. Examples of a filter I want to make is whether a product is currently available (if a checkbox is selected or not) or is available in a certain week (which I save with a string like 19 July 2021 - 25 July 2021, and each product has an array of those strings), and I want to group and filter based on those values. Looking at https://www.sanity.io/docs/dynamically-group-list-items-with-a-groq-filter I only see examples to filter by documents, not a field's value, even though it's stated at the beginning of the post.
AI Update

Good news! You absolutely can filter and group by field values (not just documents) in Sanity Studio's Structure Tool. Let me give you concrete examples for your specific use cases.

Filtering by Field Values

You can use GROQ filters directly on field values like checkboxes, strings, arrays, etc. Here's how to handle your scenarios:

1. Filter by Checkbox (Currently Available)

import {structureTool} from 'sanity/structure'

export default defineConfig({
  plugins: [
    structureTool({
      structure: (S) =>
        S.list()
          .title('Products')
          .items([
            S.documentList()
              .title('Available Products')
              .filter('_type == "product" && isAvailable == true'),
            S.documentList()
              .title('Unavailable Products')
              .filter('_type == "product" && isAvailable == false'),
            S.divider(),
            S.documentTypeListItem('product').title('All Products')
          ])
    })
  ]
})

2. Filter by Array of Strings (Week Availability)

For filtering products available in a specific week:

S.documentList()
  .title('Products Available This Week')
  .filter('_type == "product" && $week in availableWeeks')
  .params({week: '19 July 2021 - 25 July 2021'})

Or create a dynamic list with multiple week options:

const weeks = [
  '19 July 2021 - 25 July 2021',
  '26 July 2021 - 1 August 2021',
  '2 August 2021 - 8 August 2021'
]

S.list()
  .title('Products by Week')
  .items([
    ...weeks.map(week =>
      S.documentList()
        .title(week)
        .filter('_type == "product" && $week in availableWeeks')
        .params({week})
    )
  ])

3. Combining Multiple Field Filters

You can combine multiple conditions:

S.documentList()
  .title('Available Products This Week')
  .filter('_type == "product" && isAvailable == true && $week in availableWeeks')
  .params({week: '19 July 2021 - 25 July 2021'})

Key Points

  • Any field value works: You can filter by booleans, strings, numbers, arrays, dates, etc.
  • GROQ operators: Use ==, !=, >, <, in, match, etc. for different comparisons
  • Parameters: Use .params() to make filters dynamic and reusable
  • The Structure Tool customization course shows this is fully supported

The confusion might be that some examples focus on reference fields (which are documents), but the same .filter() method works for any field type in your schema. You're just writing GROQ filters that evaluate field values directly!

Show original thread
4 replies
You can add anything into your filter that resolves to true/false. For example, let’s assume your document has a
_type
of
product
. A basic filter to return all your products would be
*[_type == "product"]
, which will consider all documents and return those where
_type == "product"
resolves to
true
. If you have a checkbox field called
available
, you could add that to your filter like this:

*[_type == "product" && available]
Which is the same as:


*[_type == "product" && available == true]
Any products returned by this query would have a
_type
of
product
and
available
checked (i.e.,
true
), which resolves to:

*[true && true]
or simply


*[true]
Products where
available
is
false
would resolve to:

*[true && false]
which is


*[false]
… and would therefore not satisfy the query.

As for availability in a certain week, that might be difficult if the date is stored as a start and end date as a string. I’d suggest storing them as
dates or datetimes (you only need to store one, as the other is just 7 days before/after), since then you can use comparison operators (
<
,
>
,
<=
,
>=
,
==
) to determine if you satisfy the query. Just like before, your comparison will resolve to a true/false value. You can pass dates into your query from your front end as parameters , which get included in the query and can return documents dynamically.
Thanks Geoff for the quick response! I think I had tunnel visioned on the use with child receiving something like authorId from a document and had not taken a good look at the latter part of the doc, and with your explanation this now seems really simple. Thanks!
Thanks Geoff for the quick response! I think I had tunnel visioned on the use with child receiving something like authorId from a document, and with your explanation this now seems really simple. Thanks!
You’re welcome! Have fun building!

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?