Query related content by tags in Sanity

5 replies
Last updated: Nov 29, 2025
Looking for any help as I am attempting to query for "related content" based on the tags of a resource. Details in 🧡
AI Update

I'll help you query for related content based on tags! This is a common use case, and there are several effective patterns you can use depending on your schema structure.

Basic approach for array of tag references

If your resource has a tags field that's an array of references to tag documents, here's the core pattern:

*[
  _type == "resource" 
  && _id != ^._id  // exclude current resource
  && count(tags[@._ref in ^.^.tags[]._ref]) > 0
]

Complete query with projections

Here's a more complete example that gets a resource and its related content:

*[_type == "resource" && _id == "your-resource-id"][0] {
  _id,
  title,
  tags[]->{title},
  "related": *[
    _type == "resource"
    && _id != ^._id
    && count(tags[@._ref in ^.^.tags[]._ref]) > 0
  ][0...5] {  // limit to 5 related items
    _id,
    title,
    slug
  }
}

Key concepts explained

The trick here uses count() to check if any array elements match:

  • tags[@._ref in ^.^.tags[]._ref] filters tags where the _ref matches any _ref in the parent resource's tags
  • The double caret ^.^ is needed because tags[query] creates its own closure - the first ^ escapes the tag filter closure, and the second ^ escapes the subquery closure
  • count(...) > 0 returns true if there's any overlap

If tags are strings instead of references

If your tags are just an array of strings like ["tag1", "tag2"], the query is simpler:

*[
  _type == "resource"
  && _id != ^._id
  && count(tags[@ in ^.^.tags]) > 0
]

Alternative: Using tag titles

If you want to match based on tag titles rather than _ref:

*[
  _type == "resource"
  && _id != ^._id
  && count(tags[@->title in ^.^.tags[]->title]) > 0
]

Sorting by relevance

You can also sort related content by how many tags they share:

*[_type == "resource" && _id == "your-resource-id"][0] {
  _id,
  title,
  "related": *[
    _type == "resource"
    && _id != ^._id
    && count(tags[@._ref in ^.^.tags[]._ref]) > 0
  ] {
    _id,
    title,
    "matchCount": count(tags[@._ref in ^.^.tags[]._ref])
  } | order(matchCount desc)[0...5]
}

You can test these queries interactively at groq.dev. There's also a great community discussion with additional examples and explanations about this exact pattern.

If you share more details about your schema structure (whether tags are references, strings, or something else), I can help refine the query further!

Show original thread
5 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.

Was this answer helpful?