How to get the titles of tags attached to stories in Sanity.io

3 replies
Last updated: Jun 11, 2020
I'm struggling with what I feel certain is a very basic query. So maybe someone will be able to give me a quick easy answer!
I have documents of
_type == "story"
. Each Story has a field of
tags
which is an array of references to document
_type == "storyTag"
.
Story schema:

export default {
  name: 'story',
  title: 'Story',
  type: 'document',
  fields: [
    {
      name: 'author',
      title: 'Author',
      type: 'string',
    },
    {
      name: 'tags',
      title: 'Tags',
      type: 'array',
      of: [{ type: 'reference', to: { type: 'storyTag' } }],
    },
...
}
Story Tag schema:

export default {
  name: 'storyTag',
  title: 'Story Tag',
  type: 'document',
  fields: [
    {
      name: 'title',
      title: 'Title',
      type: 'string',
    },
  ],
}
I want to query my dataset and get all the stories, with the titles of the tags attached to it.

Using:

`*[ _type == "story" ]{
   _type,
  "title": author,
  tags
}`
gets me the stories with an array of tags attached, but that array looks like this:

[{
_key: "b251db713b80"
_ref: "17d1190e-c8d2-40a4-8e12-97875ed95bf1"
_type: "reference"
}]
How can I get the title of the tags? I've tried a variety of different queries but none have worked - I'm sure I'm missing something simple, but any help would be much appreciated.
🙏
AI Update

You're really close! The solution is to use the dereference operator -> in GROQ to resolve those references to the actual tag documents.

Here's how to modify your query:

*[_type == "story"]{
  _type,
  "title": author,
  tags[]->
}

The key is tags[]-> which does two things:

  1. tags[] - iterates over each item in the tags array
  2. -> - dereferences each reference to fetch the actual storyTag document

This will give you the full storyTag documents in your results. If you only want the titles (which sounds like what you need), you can be more specific:

*[_type == "story"]{
  _type,
  "title": author,
  tags[]->{title}
}

Or even cleaner, map it to just an array of title strings:

*[_type == "story"]{
  _type,
  "title": author,
  "tagTitles": tags[]->title
}

The reference access operator (->) internally executes a subquery to fetch the referenced document by its _id, replacing the reference object with the actual document data. When you combine it with array notation [] and projections, you can extract exactly the fields you need from those referenced documents.

Still new to this, but does this do it?
*[ _type == "story" ]{
   _type,
  "title": author,
  "tags": tags[]->title
}
user L
honestly - I thought I'd tried exactly that, but there must have been something wrong because this works like a charm. Thank you for taking the time!
np, i recently went down the "how do i resolve all arbitrarily nested references" path, this was a solution if i knew all the nested paths (which I didnt)

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?