Querying for all authors and excluding the author of the current article in Sanity.io

13 replies
Last updated: Jan 21, 2022
How would one query for all authors and exclude the author of the current article the user is on?
AI Update

To query for all authors and exclude the author of the current article, you'd use GROQ's filter operators combined with reference comparison. Here's how:

Basic approach - if you know the author ID:

*[_type == "author" && _id != $currentAuthorId]

Within an article query using the ^ operator:

The ^ operator refers to the enclosing document, which is perfect for this use case:

*[_type == "article" && _id == "current-article-id"]{
  title,
  author->{name, bio},
  "otherAuthors": *[_type == "author" && _id != ^.author._ref]{
    name,
    bio
  }
}

In your application code:

// Pass the author ID as a parameter
const otherAuthors = await client.fetch(
  `*[_type == "author" && _id != $authorId]`,
  { authorId: currentArticle.author._ref }
)

Complete example for an article page:

*[_type == "article" && slug.current == $slug][0]{
  title,
  body,
  author->{
    _id,
    name,
    bio,
    image
  },
  "otherAuthors": *[_type == "author" && _id != ^.author._ref]{
    _id,
    name,
    bio,
    image
  }
}

The key concepts here:

  1. != operator - The "not equal" operator filters out matching values
  2. ^ operator - References the enclosing/parent document in nested queries
  3. .\_ref - When comparing references, use the _ref property which contains the referenced document's _id

This pattern works whether the author field is a direct reference or part of a more complex structure. Just adjust the path to match your schema (e.g., ^.author._ref vs ^.authors[0]._ref for array references).

If you have an
authors
array with refs to `person`:
*[
  _id == "86e778c1-8e64-41e2-8101-9166efa68a63"
]{
  _id,
  title,
  authors,
  "otherAuthors": *[_type == "person" && !(_id in ^.authors[]._ref)]{name}
}
If you have an
author
 reference field with ref to `person`:
*[
  _id == "86e778c1-8e64-41e2-8101-9166efa68a63"
]{
  _id,
  title,
  author,
  "otherAuthors": *[_type == "person" && _id != ^.author._ref]{name}
}

user Y
beat me to it!
If you have an
authors
array with refs to `person`:
*[
  _id == "86e778c1-8e64-41e2-8101-9166efa68a63"
]{
  _id,
  title,
  authors,
  "otherAuthors": *[_type == "person" && !(_id in ^.authors[]._ref)]{name}
}
If you have an
author
 reference field with ref to `person`:
*[
  _id == "86e778c1-8e64-41e2-8101-9166efa68a63"
]{
  _id,
  title,
  author,
  "otherAuthors": *[_type == "person" && _id != ^.author._ref]{name}
}

user Y
beat me to it!
🤔 so right now I am fetching an article via a slug which has an author. So the query looks like
export const postQuery = groq`
  {
    'post': *[_type == "post" && slug.current == $slug] | order(_updatedAt desc)[0] {
      ${postFields}
    },
    "morePosts": *[_type == "post" && slug.current != $slug] | order(publishedAt desc, _updatedAt desc)[0...4] {
      ${postFields}
    }
  }
`
where
postFields
looks like
const postFields = `
  _id,
  _updatedAt,
  title,
  publishedAt,
  mainImage,
  "categories": categories[]->title,
  "slug": slug.current,
  "author": author->{name, 'slug': slug.current, image, bio},
  excerpt,
  body,
  featuredArticle
`
So adding _`"otherAuthors": *[_type == "author" && _id != ^.author.
ref]{name},` in the
postFields
gives it to me on every post. However, I just wanted to pass the slug in and return the others that didn't write that particular article.
🤔 so right now I am fetching an article via a slug which has an author. So the query looks like
export const postQuery = groq`
  {
    'post': *[_type == "post" && slug.current == $slug] | order(_updatedAt desc)[0] {
      ${postFields}
    },
    "morePosts": *[_type == "post" && slug.current != $slug] | order(publishedAt desc, _updatedAt desc)[0...4] {
      ${postFields}
    }
  }
`
where
postFields
looks like
const postFields = `
  _id,
  _updatedAt,
  title,
  publishedAt,
  mainImage,
  "categories": categories[]->title,
  "slug": slug.current,
  "author": author->{name, 'slug': slug.current, image, bio},
  excerpt,
  body,
  featuredArticle
`
So adding _`"otherAuthors": *[_type == "author" && _id != ^.author.
ref]{name},` in the
postFields
gives it to me on every post. However, I just wanted to pass the slug in and return the others that didn't write that particular article.
you mean you want
otherAuthors
to be a property on the root object?
So, just a flat array of all other authors, alongside your
post
and
morePosts
arrays?
🤐
😬
Yup! My use case is adding a "Discover Authors" section
Actually... if I just add it to the single post, that should be fine
So like
export const postQuery = groq`
  {
    'post': *[_type == "post" && slug.current == $slug] | order(_updatedAt desc)[0] {
      ${postFields},
      "otherAuthors": *[_type == "author" && _id != ^.author._ref]{
        name,
        'slug': slug.current,
        role,
        image
      }
    },
    "morePosts": *[_type == "post" && slug.current != $slug] | order(publishedAt desc, _updatedAt desc)[0...4] {
      ${postFields}
    }
  }
`
would probably be the smarter way to do it

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?