Query array object fields by type in Sanity GROQ

3 replies
Last updated: Jun 10, 2023
Is there a way to query all fields of a certain type (e.g all those of type string) among the fields of an array?
If I have this schema:

export default {
  name: "exampleSchema",
  title: "Example Schema",
  type: "document",
  fields: [
    {
      name: "objects",
      title: "Objects",
      type: "array",
      of: [
        {
          name: "object",
          type: "object",
          fields: [
            {
              name: "title",
              title: "Title",
              type: "string",
            },
            {
              name: "url",
              title: "URL",
              type: "slug",
            },
            {
              name: "randomString",
              title: "Random String",
              type: "string",
            },
          ],
        },
        {
          name: "objectTwo",
          type: "object",
          fields: [
            {
              name: "name",
              title: "Name",
              type: "string",
            },
            {
              name: "url",
              title: "URL",
              type: "slug",
            },
            {
              name: "evenMoreRandomString",
              title: "Even More Random String",
              type: "string",
            },
          ],
        },
      ],
    },
  ],
};
I would like to retrieve something like this:

[…] 1 item
    0:{…} 1 property
    objects:[…] 2 items
        0:{…} 2 properties
            title: asd
            randomString: asdasdasd
        1:{…} 2 properties
            name: asd
            evenMoreRandomString: asdasdasd
I thought maybe I could do something like this:

*[_type == "exampleSchema"] {
  objects[] {
    "stringFields": getFields(@)[_type == "string"]
  }
}
Thanks a lot!
AI Update

Unfortunately, GROQ doesn't have a built-in way to dynamically filter object properties by their schema type. GROQ operates on the actual data values in your documents, not on the schema metadata itself, so there's no getFields() function or ability to introspect which fields were defined as type: "string" in your schema definition.

Why this doesn't work:

GROQ queries run against your stored data, not your schema definitions. When you query, GROQ only sees the actual values in your documents—it has no knowledge that a particular field was defined as a string type versus a slug type in your schema. There's no type() function that can inspect schema metadata or determine the original type definition.

What you can do instead:

Since you need to be explicit, here are your options:

  1. Manually project the string fields you want:
*[_type == "exampleSchema"] {
  objects[] {
    title,
    randomString,
    name,
    evenMoreRandomString
  }
}
  1. Use conditional projections based on object type:

If the different object types in your array have different string fields:

*[_type == "exampleSchema"] {
  objects[] {
    _type == "object" => {
      title,
      randomString
    },
    _type == "objectTwo" => {
      name,
      evenMoreRandomString
    }
  }
}
  1. Get all fields with the spread operator:

If you want everything from the objects:

*[_type == "exampleSchema"] {
  objects[] {
    ...
  }
}

This gets you all fields including the url slugs. You'd then need to filter out non-string fields in your application code where you have access to your schema definitions.

  1. Filter in application code:

If you truly need dynamic type-based filtering, the most practical approach is to fetch all the data and filter it in your application where you have access to both the schema definitions and the data. You could create a helper function that knows your schema and filters out non-string fields.

The bottom line: GROQ is designed for querying content data, not for introspecting schema metadata, so you'll need to explicitly specify which fields you want in your projections or handle the filtering in your application layer where you have access to your schema definitions.

Show original thread
3 replies
Hi
user W
. Unfortunately, those values won’t be accessible using GROQ since they’re not stored with the data. Each schema type exists for the Studio, but the Content Lake won’t care about them. You could edit the JSON and make
objectTwo
a string,
object.title
an array, etc.
It might be possible to give guidance if we know a bit more about why you want to target and return the strings. One possibility might be to infer all the strings from the schema and then use GROQ to query for those values.
Thanks a lot, (Removed Name). I found a workaround.My schema was actually:

footerMenu(document)
   columns(array)
      terms(document)
      help(document)

Thanks a lot, (Removed Name). I found a workaround.My schema was actually:

footerMenu(document)
   columns(array) of:
      terms(document)
      help(document)

terms(document)
   title
   slug
   legalNotice(object)
      title
      slug
   privacyPolicy(object)
      title
      slug
   ...

help(document)
   title
   slug
   shipping(object)
      title
      slug
   exchanges(object)
      title
      slug
   ...
What I wanted was to query all objects within each column of the columns array. So that I would get:


legalNotice {
   title
   slug
},
privacyPolicy {
   title
   slug
},
shipping {
   title
   slug
},
exchanges {
   title
   slug
}
My solution was simply to change the schemas and put the objects inside an array:


terms(document)
   title
   slug
   subItems(array)
      legalNotice(object)
         title
         slug
      privacyPolicy(object)
         title
         slug
   ...

help(document)
   title
   slug
   subItems(array)
      shipping(object)
         title
         slug
      exchanges(object)
         title
         slug
   ...
I guess that was the obvious solution, right? I'm new to groq.

The only problem is I had to manually reenter all data inside subItems.

Thanks a lot!

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?