Querying for documents by reference in a post and tag schema

3 replies
Last updated: May 22, 2023
Does anyone know how to query for documents by reference? I have a post document and a tag document. I want to get posts that include any of the tags in an array of tags, but I can't seem to get it to work.
i've created a gist if anyone can help. I've added the query I'm using right now, the schemas for tag and post, and the code for the request i'm making


https://gist.github.com/ellismarte/10bfafe50c1465bcb89d645b82e74f6d#file-queries-L1
AI Update

I can see the issue! Looking at your gist, you're trying to use $tags in tags[].tag but the problem is with how you're comparing the arrays. The in operator in GROQ checks if a single value exists in an array, but you're passing an array of tag references and trying to match them against dereferenced tag strings.

Here's the fix for your query:

export const getSuggestedPostsByTagsQuery = `{
  "similarPosts": *[_type == "post" && slug.current != $slug && references(*[_type == "tag" && tag in $tags]._id)] | order(date desc, _updatedAt desc) [0...2] {
    ${postFields}
  }
}`;

And update your request to pass just the tag strings:

const { similarPosts } = await getClient(preview).fetch(
  getSuggestedPostsByTagsQuery,
  {
    slug: params.slug,
    tags: post.tags.map((tag) => tag.tag), // This is correct - array of tag strings
  }
);

How this works:

The references() function is specifically designed for querying by reference. It checks if any of the document's reference fields point to documents matching the inner query. The inner query *[_type == "tag" && tag in $tags]._id finds all tag document IDs where the tag string is in your array, then references() checks if the post references any of those tag documents.

Alternative approach if you want to be more explicit:

*[_type == "post" && slug.current != $slug && count((tags[]->tag)[@ in $tags]) > 0]

This dereferences all the tags (tags[]->tag), checks which ones are in your $tags array, counts them, and only returns posts where at least one tag matches.

Both approaches will work, but references() is generally more performant for this type of reference matching since it leverages Sanity's indexing better, as discussed in the query optimization guide.

You’ll need to do something similar to this !
thank you!
You’re welcome!

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?