Help needed with fetching drafts from referenced documents using groq queries in Slack thread.

3 replies
Last updated: Jul 20, 2023
hii everyone, I need some help fetching drafts from documents referenced within other documents using groq querys, the client is using a raw perspective btw, any help is greatlt appreciated!!

this is my current query

export const regionQuery = (region: string, pre: string) => {
return `*[slug.current == "${region}" && (${pre}(_id in path("drafts.**")))] {
"title": title,
'Points': mapPoints[] -> {
_id,
title,
location,
geoUrl,
geoData,
body,
mainImage,
}
}`;
};

im attaching an example pic of the referenced documents!
AI Update

Looking at your query, the issue is that you're checking if the parent document is a draft (_id in path("drafts.**")), but when you use the reference operator -> to dereference mapPoints[], it follows the reference ID exactly as stored. Since you're using the raw perspective, both drafts and published documents exist in your dataset, but references typically store the published ID (without the drafts. prefix).

Here's the problem: when you dereference with ->, it retrieves whatever document matches the stored reference ID. If the reference points to some-id, it won't automatically fetch drafts.some-id even though you're using the raw perspective.

Solution: Use a manual draft prioritization pattern

You need to explicitly fetch both the draft and published versions of referenced documents and prioritize drafts. Here's how to modify your query using the draft prioritization pattern from Sanity:

export const regionQuery = (region: string, pre: string) => {
  return `*[slug.current == "${region}" && (${pre}(_id in path("drafts.**")))] {
    "title": title,
    'Points': mapPoints[]._ref {
      "ref": @,
      "doc": *[_id == "drafts." + ^.ref || _id == ^.ref] 
        | score(_id in path("drafts.**")) 
        | order(_score desc)[0]
    }.doc {
      _id,
      title,
      location,
      geoUrl,
      geoData,
      body,
      mainImage,
    }
  }`;
};

This approach:

  1. Gets the reference IDs from mapPoints[]._ref
  2. For each reference, queries for both the draft (drafts.{id}) and published version
  3. Uses score() to prioritize drafts (giving them a higher score)
  4. Takes the top result with [0]

Alternative: Use previewDrafts perspective (recommended)

The easier solution is to use the previewDrafts perspective instead of raw. This perspective automatically prioritizes drafts over published documents, so the -> operator will naturally fetch draft versions when they exist:

// In your Sanity client configuration
const client = createClient({
  // ... other config
  perspective: 'previewDrafts',
})

Then your original query structure would work as expected:

export const regionQuery = (region: string, pre: string) => {
  return `*[slug.current == "${region}"] {
    "title": title,
    'Points': mapPoints[] -> {
      _id,
      title,
      location,
      geoUrl,
      geoData,
      body,
      mainImage,
    }
  }`;
};

The previewDrafts perspective is specifically designed for preview scenarios where you want drafts to take precedence, which sounds like exactly what you need. The raw perspective shows everything as-is (both drafts and published), which is why you're seeing this behavior.

Are the points the documents that would be drafts? If so, you’ll need to do a full subquery to get them, as the
->
operator will only get the published version.
thank you so much!! i was hoping to avoid all that, so i solved it using the new perspective option!! it really changes the game
Great!!

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?