GROQ: Query nested object text content and filter by matching word
Looking at your data structure, you need to search through nested arrays to find text within your Portable Text blocks. Here's how to do it:
*[_type == "post" && contentBlocks[].mainText[].children[].text match "omnis-aut-voluptatem"]{
slug
}This will return all posts where any text in your nested structure matches the word you're searching for. The key is understanding how GROQ handles nested arrays - you use [] to "flatten" each level of the array structure.
Breaking down the path:
contentBlocks[]- traverse the contentBlocks array.mainText[]- traverse the mainText array inside each contentBlock.children[]- traverse the children array inside each block.text- access the actual text content
The match operator performs tokenized text search, so it'll find whole words within your text. It breaks text into searchable terms, so searching for "omnis" would match "omnis-aut-voluptatem" since the dash acts as a word separator.
To get just the slug values as a simple array:
*[_type == "post" && contentBlocks[].mainText[].children[].text match "omnis"]{
"slug": slug.current
}Pro tip: If you need to search for multiple words or do more complex searches, you can combine conditions:
*[_type == "post" && (
contentBlocks[].mainText[].children[].text match "omnis" ||
contentBlocks[].mainText[].children[].text match "beatae"
)]{
slug
}The match operator is great for full-text search, but if you need exact string matching or prefix matching, you'd want to use string functions like string::startsWith() instead.
Show original thread6 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.