Querying references in Sanity: how to search posts by category

15 replies
Last updated: Jun 21, 2021
Hi everyone,I'm quite new to sanity and I'm learning through a series of tutorial but I've still some trouble with querying references.
Say i have post document like this:

fields: [
    
{
      
name: 'title',
      
title: 'Title',
      
type: 'string',
    
},
   
{
      
name: 'categories',
      
title: 'Categories',
      
type: 'array',
      
of: [{type: 'reference', to: {type: 'category'}}],
    
},
    
},
   and a category document like this:

fields: [
    
{
      
name: 'title',
      
title: 'Title',
      
type: 'string',
    
}

]

Question is how can I query all posts based on a dynamically provided category?
Any help will greatly appreciated. Thanks
AI Update

Great question! Filtering posts by category is a common pattern in Sanity. Based on your schema where posts have an array of category references, here's how to query all posts for a specific category using GROQ:

The Solution

The key is using the references() function in GROQ. Here's the query:

*[_type == "post" && references($categoryId)]

Where $categoryId is a parameter you pass in with the _id of the category you want to filter by.

Complete Example

If you want to include the category details in your results, you can dereference it:

*[_type == "post" && references($categoryId)] {
  _id,
  title,
  categories[]->
}

The -> operator dereferences the category references, giving you the full category documents instead of just the reference IDs.

Filtering Out Drafts

In production, you'll want to exclude draft documents:

*[_type == "post" && !(_id in path("drafts.*")) && references($categoryId)]

Using with Client Code

Here's how you'd use this with the Sanity client:

const posts = await client.fetch(
  `*[_type == "post" && references($categoryId)] {
    _id,
    title,
    categories[]->
  }`,
  { categoryId: 'your-category-id-here' }
)

The references() function works perfectly with arrays of references - it checks if any item in your categories array references the provided ID. Check out the GROQ parameters documentation for more details on passing parameters to your queries.

By "query", do you mean GROQ, GraphQL, or other?
Groq?
So do you want to pull all posts that reference a certain category?
exactly
(categories[]->title match ["...."])
Thanks, Christopher, I will try that.
Hi Christopher I tried that and I got :• No documents found in dataset 
production
 that match query:
Here is the query i use:
*[_type == "post" && (categories[]->tiltle match "nodejs")]
When I try :
*[_type == "category"]{

title

}
here is what i get:
"result":*[*_2 items_

0:*{*_1 item_

"title":"reactjs"

}

1:*{*_1 item_

"title":"nodejs"

}

]
and when I do try this:
*[_type == "post" ]{

title,


categories[]->{title}

}
I get this:


"result":*[*_2 items_

0:  *{*  _2 items_

"categories":*[*_1 item_

0:*{*_1 item_

"title":"nodejs"

}

]


"title":"Another one"

}

1:*{* _2 items_

"categories":*[*_1 item_

0:*{*_1 item_

"title":"reactjs"

}

]

"title":"The first of many to come"

}

]
Sorry if the information is quite much. I'm just hoping i give you ab better insight as what i'm struggling with
Basically, i will like a use to search post by category. That is all
Hey Donald! This section on filters in the documentation could be helpful. Depending on how you have your document set up, it would look something like this:
*[_type == 'post' && category == 'your-category']

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?