GROQ Query Response - Making a Separate Property the Property an Object

9 replies
Last updated: Oct 6, 2021
I'm having trouble with a query. Not sure if what I'd like to do is possible.
The query:

*[_type == "post"][0] {
  	mainImage,
    "lqip": mainImage.asset->metadata.lqip
}
returns:

{
  "lqip": "data:image/jpeg;base64,/9j/2wBDAAYEBQYFBAYGBQYHBw...",
  "mainImage": {
    "_type": "image",
    "altText": "Mountains with pink sky and turquoise water",
    "asset": {
      "_ref": "image-db89f238f31f609d2cac163248de2105d4c1f06c-3374x2000-jpg",
      "_type": "reference"
    }
  }
}
I'd like
lqip
to be a property of the
mainImage
object:
{
  "mainImage": {
    "_type": "image",
    "altText": "Mountains with pink sky and turquoise water",
    "lqip": "data:image/jpeg;base64,/9j/2wBDAAYEBQYFBAYGBQYHBw...",
    "asset": {
      "_ref": "image-db89f238f31f609d2cac163248de2105d4c1f06c-3374x2000-jpg",
      "_type": "reference"
    }
  }
}
Is there a way to achieve this?
AI Update

Yes, absolutely! You can achieve this using the GROQ spread operator (...) to merge the lqip property into the mainImage object. Here's how:

*[_type == "post"][0] {
  "mainImage": {
    ...mainImage,
    "lqip": mainImage.asset->metadata.lqip
  }
}

This works by:

  1. Creating a new mainImage object in the projection
  2. Using ...mainImage to spread all the existing properties from the original mainImage field (including _type, altText, and asset)
  3. Adding the lqip property by dereferencing the asset metadata

The result will be exactly what you're looking for:

{
  "mainImage": {
    "_type": "image",
    "altText": "Mountains with pink sky and turquoise water",
    "asset": {
      "_ref": "image-db89f238f31f609d2cac163248de2105d4c1f06c-3374x2000-jpg",
      "_type": "reference"
    },
    "lqip": "data:image/jpeg;base64,/9j/2wBDAAYEBQYFBAYGBQYHBw..."
  }
}

The ellipsis/spread operator (...) in GROQ is perfect for this kind of object composition where you want to keep all existing fields while adding new ones. Just note that the spread operator is always evaluated first regardless of where it appears in the projection, so any properties you define after it will override properties with the same name from the spread.

Could you try:

*[_type == 'post'][0]{
  mainImage{
  	...,
  	'lqip': ^.mainImage.asset->metadata.lqip,
  }
}
Hey Geoff, I'll give it a try.
Just getting on a computer to check this.
Just tried and it works perfectly.
Thanks very much Geoff. Still getting my mind wrapped around these kinds of queries. Really appreciate the help.
This should do the same and removes some complexity:

*[_type == 'post'][0]{
  mainImage{
  	...,
  	'lqip': asset->metadata.lqip,
  }
}
Oh cool, I'll try it.
You’re welcome! Yes, they can get complex but are sure powerful. It’s fun when you try a query and it works. 🙂
Definitely! Yeah that one is simpler and intuitive. Works perfectly.

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?