sanitygroq

How to filter Sanity.io dataset based on a field on references


How to get all posts by a category slug in GROQ?

You can see that a post is added to one or more categories. I would like to get all posts by a category slug to show the posts on a category page. I am new to Sanity.io's GROQ. All the tutorials I have found on creating a blog with sanity.io and next.js have not covered it to show a category page showing posts from a category.

Post schema:

export default {
  name: 'post',
  title: 'Post',
  type: 'document',
  fields: [
    {
      name: 'title',
      title: 'Title',
      type: 'string',
    },
    {
      name: 'slug',
      title: 'Slug',
      type: 'slug',
      options: {
        source: 'title',
        maxLength: 96,
      },
    },
    {
      name: 'author',
      title: 'Author',
      type: 'reference',
      to: {type: 'author'},
    },
    {
      name: 'mainImage',
      title: 'Main image',
      type: 'image',
      options: {
        hotspot: true,
      },
    },
    {
      name: 'categories',
      title: 'Categories',
      type: 'array',
      of: [{type: 'reference', to: {type: 'category'}}],
    },
    {
      name: 'publishedAt',
      title: 'Published at',
      type: 'datetime',
    },
    {
      name: 'body',
      title: 'Body',
      type: 'blockContent',
    },
  ],

  preview: {
    select: {
      title: 'title',
      author: 'author.name',
      media: 'mainImage',
    },
    prepare(selection) {
      const {author} = selection
      return Object.assign({}, selection, {
        subtitle: author && `by ${author}`,
      })
    },
  },
}

I have tried the following:

const query = `*[_type == 'post' &&  $slug in [categories[]-> {slug}] ]{ _id, title, slug, publishedAt, categories[]-> {title,slug}} | order(publishedAt) [0...10]`;

const posts = await client.fetch(
        query,
        { slug }
    );

console.log("posts", posts);

Solution

  • I got the solution at Sanity's slack channel. The following code helps to get the posts from a category by it's slug.

    `*[_type == 'post' && $slug in categories[]->slug.current ]`;