Querying array of references in Sanity schema and resolving null values

10 replies
Last updated: Jan 30, 2021
I have an array of references to a
country
schema type, does this query look like it should work? It always just returns NULL values for me
*[_type == "post" && slug.current == 'hello-world'] | order(_updatedAt desc) {
  title,
  'test': countries[].country->{title, slug}
}
AI Update

I can see the issue with your query! The problem is with the syntax countries[].country->. You're trying to dereference inside an array, but the .country part is creating a syntax issue.

The correct syntax depends on your schema structure:

If your array items ARE the references directly:

*[_type == "post" && slug.current == 'hello-world'] | order(_updatedAt desc) {
  title,
  'test': countries[]->{title, slug}
}

If your array items are objects that CONTAIN a reference field called country:

*[_type == "post" && slug.current == 'hello-world'] | order(_updatedAt desc) {
  title,
  'test': countries[]{
    country->{title, slug}
  }
}

The key difference is:

  • countries[]-> - Use this when the array items themselves are references
  • countries[]{country->} - Use this when the array items are objects with a country reference field inside

Based on your query mentioning .country, I suspect you have the second structure (objects containing a reference), so the second syntax should work for you.

As explained in the reference access operator documentation, when working with arrays containing references, you need to use the array projection syntax []{} and then apply the dereference operator -> to the reference field within each array item.

The reason you're getting NULL values is that countries[].country-> isn't valid GROQ syntax - the parser doesn't know how to handle the .country part before the dereference operator.

For that to work I would expect your schema to look something like this:

{
  name: "post",
  title: "Posts",
  type: "document",
  fields: [
    {
      name: 'title',
      title: 'Title',
      type: 'string',
    },
    {
      type: 'array',
      name: 'countries',
      title: 'Countries',
      of: [{
        type: 'object',
        fields: [
          {
            name: 'country',
            title: 'Country',
            type: 'reference',
            to: [{ type: 'countries' }],
          },
        ],
      }],
    },
  ],
}
This is what my schema looks like. Would this be the ‘correct’ way to link multiple countries/categories to a blog post
{
  name: 'countries',
  title: 'Countries',
  type: 'array',
  of: [{ type: 'reference', to: { type: 'country' } }],
}, 
Yes, that should work. But you’re getting null values?
*[_type == "post" && slug.current == 'hello-world'] | order(_updatedAt desc) {
  title,
  'test': countries[]->{title, slug}
}

Aha! That worked. Seems like it should be done differently from what it says in the docs
Could you try that? My example had an array of objects of references. Yours is an array of references.
Great! Glad it worked.
The difference lies in whether the array contains objects or the direct items.
Yea makes sense now. Would you recommend to create an array of objects?
If you’re only linking directly to references, your way should work great. Where you’ll want to use objects is when you need to create arrays of arrays or arrays containing both objects and primitives. Let me find a link here…

https://www.sanity.io/docs/array-type#two-limitations-fNBIr84P
Thanks for sharing that and thanks for helping 🤙

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?