Issue with fetching data from an array of references and non-references in a groq query.

3 replies
Last updated: Dec 14, 2023
Hey! I'm trying to create a groq query that fetches data from an array of both references and not references.
This is what I currently have, but the not-references returns null, and if I remove the -> after contentLoggedin[], all the other entries return null!


contentLoggedIn[] -> {
    _type == 'staticSlider' => {
      _type,
      _key,
      textIsCentered,
      textColor,
      header {
        headline,
        body,
        callToAction {
          text,
          link
        }
      },
      items[] -> {
        title,
        filterUrl,
        urlSlug,
        image {
          "asset": {
            "url": asset->url
          }
        },
        description
      }
    },
    _type == 'dynamicSlider' => {
      _type,
      content
    }
}
Basically, the dynamicSlider type returns null...
AI Update

The issue you're experiencing is that when you use contentLoggedIn[] -> at the array level, GROQ tries to dereference every item in the array. This works fine for references (items with a _ref field), but returns null for inline objects that aren't references.

The reference access operator (->) only works on reference objects. When applied to non-reference inline objects like your dynamicSlider, it returns null.

The Solution

Remove the -> from the array level and only apply it where you actually have references:

contentLoggedIn[] {
  _type == 'staticSlider' => {
    _type,
    _key,
    textIsCentered,
    textColor,
    header {
      headline,
      body,
      callToAction {
        text,
        link
      }
    },
    items[] -> {
      title,
      filterUrl,
      urlSlug,
      image {
        "asset": {
          "url": asset->url
        }
      },
      description
    }
  },
  _type == 'dynamicSlider' => {
    _type,
    content
  }
}

This works because:

  • contentLoggedIn[] without -> processes each item in the array as-is
  • For both staticSlider and dynamicSlider items (which appear to be inline objects based on your projection), you access their fields directly
  • The items[] array within staticSlider appears to contain references, so you use -> there specifically

If You Have a Mix of References and Inline Objects

If your contentLoggedIn array actually contains some items that are references and some that are inline objects, you'll need to handle them differently. Based on the Sanity community answer on mixed content, you can manually check each type:

contentLoggedIn[] {
  _type == 'staticSlider' => @->{
    _type,
    _key,
    textIsCentered,
    textColor,
    header {
      headline,
      body,
      callToAction {
        text,
        link
      }
    },
    items[] -> {
      title,
      filterUrl,
      urlSlug,
      image {
        "asset": {
          "url": asset->url
        }
      },
      description
    }
  },
  _type == 'dynamicSlider' => @{
    _type,
    content
  }
}

In this pattern, @ represents the current item. If staticSlider items are references, use @-> to dereference them. If dynamicSlider items are inline objects, use @ to access them directly.

However, based on your original query structure where you're projecting specific fields from both types, it's most likely that both are inline objects in your array, making the first solution the correct one.

What does the schema for this look like?
Hey
user M
and thanks for the response ๐Ÿ™‚
This is the schema for that specific type:


{
  name: 'contentLoggedIn',
  type: 'array',
  title: 'Content for a logged in user',
  description: 'Create, add and order the content of this landing page.',
  of: [
    {
      type: 'reference',
      title: 'Reusable Static Slider or Banner',
      to: [{ type: 'staticSlider' }, { type: 'banner' }, { type: 'twoTileBanner' }],
    },
    { type: 'dynamicSlider' },
  ],
},
And the dynamic slider is just an object with a simple object called "content" which has title and value, like this:

{
  name: 'dynamicSlider',
  type: 'object',
  title: 'Dynamic Slider',
  fields: [
    {
      name: 'content',
      type: 'string',
      title: 'Dynamic Content',
      description: 'Choose what dynamic content to display.',
      options: {
        list: [
          { title: 'Popular items', value: 'popularItems' },
          { title: 'Favourite items', value: 'favouriteItems' },
          { title: 'Recommended items', value: 'recommendedItems' },
        layout: 'radio',
      },
    },
  ],
}
Whereas the other items in the array of contentLoggedIn are references.
I figured it out ๐Ÿ™‚

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?