How to globally ignore drafts in GROQ queries without filtering each time?

11 replies
Last updated: Feb 18, 2021
Is there a way to ignore all drafts and not have to
!(_id in path('drafts.**'))
in every groq requests?
AI Update

Yes! You can use perspectives to control whether drafts are included in your queries without adding !(_id in path('drafts.**')) to every GROQ request.

The easiest solution is to set the perspective parameter to published when making your API requests. The perspectives feature provides different views of your content:

  • published - Returns only published documents (no drafts)
  • previewDrafts - Returns drafts when they exist, falling back to published versions
  • raw - Returns everything (both drafts and published documents)

How to use perspectives

In client configuration:

import {createClient} from '@sanity/client'

const client = createClient({
  projectId: 'your-project-id',
  dataset: 'production',
  useCdn: true,
  apiVersion: '2025-02-19',
  perspective: 'published' // This filters out drafts automatically
})

In individual queries:

const data = await client.fetch(
  `*[_type == "post"]`,
  {},
  {perspective: 'published'}
)

In HTTP API requests:

https://your-project.api.sanity.io/v2025-02-19/data/query/production?query=*[_type=="post"]&perspective=published

Important note about API versions

If you're using the API version 2025-02-19 or later, the default perspective changed to published, so you'll automatically get only published documents without any additional configuration. In older API versions, the default was raw, which includes both drafts and published documents.

This is much cleaner than manually filtering drafts in every query, and it gives you flexibility to switch between perspectives based on your environment (e.g., use previewDrafts for preview environments and published for production).

Show original thread
11 replies
HI User. Are you sending a token with your request? If you’re querying a public dataset then drafts will be ignored if no token is sent. I’m not sure if that’s possible in your setup.
Hmm i’d prefer the dataset remains private to be honest
Fair enough. If it’s a private dataset then I’m not sure if you can get around some sort of filter to remove the drafts.
user A
I assume you’re using a read+write token for your query. What about using a read token for those cases where you want to ignore drafts? It looks like that should work, though of course your circumstances will dictate.
I use a defined constant for this, so it doesn’t need to be re-written each time:In a constants.js file

_export_ const QUERY_OMIT_DRAFTS = "!(_id in path('drafts.**'))"

groq`*[
      _type == 'glossary'
      && ${QUERY_OMIT_DRAFTS}
    ]|{
      _id,
      title,
      name,
      "slug": slug.current,
      categories[]->{_id, title, name, "slug": slug.current}
    }`
It’s not ideal, but it’s easier than remembering the syntax to omit the drafts
I was curious if using template literal placeholders (
${QUERY_OMIT_DRAFTS}
) like that is safe, since other parameters are passed into the query. Any thoughts on that
user A
?
I can’t imagine it being a problem, though my experiences are limited. Maybe a fallback in case it fails would help? Although it’s possible it fails gracefully on its own.
My mind is on the idea of SQL injection (which is different than this) but wasn’t sure if there was any similar security risk in this approach, as GROQ offers the ability to pass parameters in, which maybe is more safe… I haven’t been able to find any information on it, but this is definitely the more convenient approach.
Oh, gotcha. Thank you. 👍 I think that would be okay as you can’t mutate from a GROQ query, but it’s something to think on, for sure.
Yeah
user J
I ended up doing something similar. Thanks everyone 🙏

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?