Using the match function in GROQ for full and partial word queries

2 replies
Last updated: Dec 12, 2024
When using the
match
function in GROQ, the full word query shows more results than the shorter query; i.e. "optimization" vs "optim"??
The 2 queries here are identical, just with a different
query
parameter:
AI Update

This behavior you're experiencing is actually expected with how the match operator in GROQ handles tokenization and wildcards. The key is understanding that match performs full-text search with tokenization, not substring matching.

When you search for "optimization" (the full word), it matches documents containing that complete token. However, when you search for "optim" (the shorter version), you're likely expecting it to match as a prefix, but match doesn't do automatic prefix matching - it looks for the exact token "optim".

Why "optimization" shows more results than "optim"

The match operator tokenizes both your search term and the content being searched. It breaks text into discrete tokens (words) based on word boundaries. So:

  • "optimization" matches documents that contain the token "optimization"
  • "optim" only matches documents that contain the exact token "optim" (not as a prefix)

If you want prefix matching behavior, you need to explicitly use the wildcard *:

// This will match "optim", "optimization", "optimal", "optimize", etc.
*[title match "optim*"]

// Without wildcard - only matches exact token "optim"
*[title match "optim"]

Important tokenization notes

The match operator splits text based on word boundaries and special characters. For example, "banana@sanity.io" would be indexed as separate tokens: ['banana', 'sanity', 'io']. The wildcard * is treated as a word character, and the operator honors Unicode word segmentation rules.

So your queries should look like:

// For prefix matching (will match "optimization", "optimize", etc.)
*[_type == "article" && title match $query + "*"]

// Or if query is already a parameter
*[_type == "article" && title match "optim*"]

Alternative for exact prefix matching

If you need more precise prefix matching without tokenization behavior, consider using the string::startsWith() function instead:

*[_type == "article" && string::startsWith(lower(title), lower($query))]

This gives you true prefix matching without the tokenization behavior of match, though it won't benefit from the full-text search indexing that match uses.

Match is looking for a full word. You can append
*
to your
$query
so that “optim” will match “optim”, “optimization”, “optimisation” and “optimusprime”
TY!

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?