How to Query all the Documents that have the Same Start of the ID as the Current Document

4 replies
Last updated: Jul 16, 2020
Ahoy 🙂 I'm trying to query all the documents that have the same start of the ID as the current document. I want to collect the different language versions of the same document. The related docs have the same ID + language suffix
"_id":"627f6815-531b-42ad-962a-f4d41159ac68"
"_id":"627f6815-531b-42ad-962a-f4d41159ac68__i18n_de"
This is what I've tried but it does not work:

*[_type == "project"] | order(_updatedAt desc) {
	_id,
	'lang':__i18n_lang, 
	title,
	'slug': slug.current,
// This is the bit that doesnt work
	"translated": *[_id match ^._id + "*"] { ... }
}
This is my document list that I'm trying to collate:

"result":[
  0:{
    "_id":"627f6815-531b-42ad-962a-f4d41159ac68"
    "lang":"en"
    "slug":"all-football-everything"
    "title":"All Football Everything"
  }
  1:{
    "_id":"627f6815-531b-42ad-962a-f4d41159ac68__i18n_de"
    "lang":"de"
    "slug":"alles-fussball-alles"
    "title":"Alles FuĂźball Alles"
  }
]
I would like a result that looks like this:

{
  "_id":"627f6815-531b-42ad-962a-f4d41159ac68"
  "lang":"en"
  "slug":"all-football-everything"
  "title":"All Football Everything"
  "translated":{
    "_id":"627f6815-531b-42ad-962a-f4d41159ac68__i18n_de"
    "lang":"de"
    "slug":"alles-fussball-alles"
    "title":"Alles FuĂźball Alles"
  }
}
Is there a way of doing this? (Using
sanity-plugin-intl-input
)
AI Update

The issue with your query is that match is designed for full-text search with tokenization, not for pattern matching with wildcards. For your use case of finding documents by ID prefix, you should use the string::startsWith() function instead.

Here's how to fix your query:

*[_type == "project"] | order(_updatedAt desc) {
  _id,
  'lang': __i18n_lang, 
  title,
  'slug': slug.current,
  "translated": *[_type == "project" && string::startsWith(_id, ^._id + "__i18n_")] {
    _id,
    'lang': __i18n_lang,
    title,
    'slug': slug.current
  }
}

The key changes:

  1. Use string::startsWith() instead of match - this does exact prefix matching
  2. Reference the parent document's ID with ^._id to access the outer document's _id field
  3. Build the prefix pattern by concatenating ^._id + "__i18n_" to match your translation suffix pattern
  4. Include the _type filter in the subquery to keep it efficient

If you want to get all translations (including other language versions), you could do:

*[_type == "project"] | order(_updatedAt desc) {
  _id,
  'lang': __i18n_lang, 
  title,
  'slug': slug.current,
  "allTranslations": *[_type == "project" && string::startsWith(_id, ^._id)][_id != ^._id] {
    _id,
    'lang': __i18n_lang,
    title,
    'slug': slug.current
  }
}

This filters for documents whose _id starts with the current document's _id, then excludes the current document itself with [_id != ^._id].

The match operator tokenizes text and treats special characters as word separators, which is why it doesn't work for precise ID matching. string::startsWith() is the right tool for prefix-based string matching in GROQ.

Ahoy JD! Strange indeed that
match
doesn’t seem to let you use
^._id
in this case, giving an internal server error. I’ll flag this one internally, thanks.
For now, you could work around it as follows:

...
"translated": *[_id > ^._id && _id < ^._id + "a"]
...
Thanks for that Peter! Your suggestion works for finding
d8b5616a-b376-4f16-929f-57b517100b43__i18n_de
from
d8b5616a-b376-4f16-929f-57b517100b43
but not for finding
d8b5616a-b376-4f16-929f-57b517100b43
from
d8b5616a-b376-4f16-929f-57b517100b43__i18n_de
. Is there a way to link the shorter ID to the longer one?What I'm trying to achieve is a language switcher that links to the translated doc no matter what document you are on
Hey again - how about this one? 🙂
...
"translated": *[(_id > ^._id && _id < ^._id + "a") || (^._id > _id && ^._id < _id + "a")]
...
Works! You're a legend. 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?