Difficulty accessing asset properties in a query, but issue was resolved.

11 replies
Last updated: Nov 3, 2022
Hey folks!I’m trying to pull an array of projects from a reference document and can’t work out how to access the asset properties.

In this query, the assetGroup is returned, but none of the asset metadata like its url is.

      const query = `{"data": *[_id == "projectsArray"] {
        "projects": projects[]{
          "builtAt": project->builtAt,
          "description": project->description,
          "id": project->_id,
          "slug": project->slug,
          "title": project->title,
          "year": project->year,
          "cover": project->cover {
            "id": cover.asset->assetId,
            "url": cover.asset->url,
            "meta": cover.asset->metadata
          },
          "assets": project->assets[]{
            assetGroup,
            "url": asset->url
          }
        }
      }}`
AI Update

Looking at your query, the issue is with how you're dereferencing the asset reference within the nested array projection. When you have an array of objects that contain asset references, you need to use the proper syntax to expand those references.

In your current query:

"assets": project->assets[]{
  assetGroup,
  "url": asset->url
}

The problem is that asset->url is trying to access url directly, but you need to properly dereference the asset first. Based on the GROQ documentation on expanding references, when you have an array of objects containing references, you need to use the dereference operator -> with a projection.

Here's the corrected approach:

const query = `{"data": *[_id == "projectsArray"] {
  "projects": projects[]{
    "builtAt": project->builtAt,
    "description": project->description,
    "id": project->_id,
    "slug": project->slug,
    "title": project->title,
    "year": project->year,
    "cover": project->cover.asset->{
      assetId,
      url,
      metadata
    },
    "assets": project->assets[]{
      assetGroup,
      "assetDetails": asset->{
        _id,
        url,
        metadata
      }
    }
  }
}}`

The key changes:

  1. For the cover image: Changed from trying to access individual properties to using a proper projection: cover.asset->{assetId, url, metadata}

  2. For the assets array: Instead of asset->url, use asset->{_id, url, metadata} to properly expand the entire asset reference and get all the fields you need

The dereference operator -> follows the reference to fetch the actual asset document. When you want multiple fields from that referenced document, you need to use a projection ->{ fields } after the dereference operator. This is explained in the section on expanding references.

If you only want the URL as a simple value in your assets array, you could also use a "naked projection" like this:

"assets": project->assets[]{
  assetGroup,
  "url": asset->url
}

But make sure asset is actually the field name in your schema. If it's named differently (like image or file), adjust accordingly.

Hey Mikhail! You don't need to expand your reference each time. You can do:
projects[]->{
  builtAt,
  description,
  id,
  slug,
  title,
  year,
  cover->{
   url,
   //other fields
  },
  assets[]{
   'url': asset->url
   //other fields
  }
}
user M
Hmm. This returns an empty object for each project.
Can you share your schema?
Edit: Do you have this wrapped in an object called project? if so:

projects[]{
 project->{
  builtAt,
  description,
  id,
  slug,
  title,
  year,
  cover->{
   url,
   //other fields
  },
  assets[]{
   'url': asset->url
   //other fields
  }
 }
}
user M
This throws an error, wrapped or unwrapped within the query.A simple test version returned a 400:

      const query = `{"projects": *[_id == "projectsArray"] {
       projects[]{
        project->{
          builtAt,
          description,
          id,
          slug,
          title,
          }
        }
      }`
Given that schema, that first query should work for you. Can you share the full query that you added that to?
Currently all I’ve got it this:
    const query = `{"projects": *[_id == "projectsArray"]{
        projects[]{
          project->{
            slug,
            cover{
              asset->{url}
            },
            assets[]{
              asset->{url}
            }
          }
        }
      }}`
My bad, I had an extra arrow with the cover. This now works. Still trying to wrap my head around assets though
I stripped it all back. This returns the slug per project, but not the cover
user M
I got my head around in the end, thank you so much! All works now 🙂
Oh great! I was just trying to put together a query link for you. Glad you got it sorted!

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?