👋 Next.js Conf 2024: Come build, party, run, and connect with us! See all events

How to make a reference inside an array of arrays in Slack thread

28 replies
Last updated: Apr 25, 2022
How can I make a reference inside an array of arrays ?
*[_type == 'presentation'][0]{
  projects[]-> {
    'presentationSlides': presentationSlides[].images, 
  },
}

presentationSlides[].images
in this case is an array of images. What I want is keep the array inside
presentationSlides
but just have the url.
So the end result looks like:

{
  projects: [
    {
      presentationSlides: [
        [
          'https://...',
          'https://...',
        ],
        [
          'https://...',
          'https://...',
        ],
      ]
    }
  ]
}
Apr 22, 2022, 3:32 PM
I'm trying to do
presentationSlides[].images[].asset->url
but it kills one level and do something like this:
{
  projects: [
    {
      presentationSlides: [
        'https://...',
        'https://...',
        'https://...',
        'https://...',
      ]
    }
  ]
}
Apr 22, 2022, 3:50 PM
So, FYI, nested arrays aren’t supported. There is a very good, basic data processing reason for this that I’m not sure I can easily state, but it’s a good reason!
The schema work arround:
• instead of
array[array[]]
• nest an object containing arrays in the schema
array[object{array[]}]
You should be able to transform the output in a groq query to something resembling what you want with some nested queries, joins, and mutations. Start
here for this.
Apr 22, 2022, 5:58 PM
I haven’t tried pushing this to its limits, but there may be a UI limitation to how many nested levels you can go. Here’s a schema snip of arr>obj>arr :
{
      name: 'arr1',
      title: 'Array One Test',
      type: 'array',
      of: [
        {
          name: 'object1',
          title: 'Object One Test',
          type: 'object',
          fields: [
            {
              name: 'arr2',
              title: 'Array Two Test',
              type: 'array',
              of: [
                {type: 'string'}
              ]
            }
          ]

        }
      ]
    },
Apr 22, 2022, 6:00 PM
Honestly, if you’re going deeper than this example, spreading out your content would be advised for the sake of easier management regardless. The middle-object also allows you to add multiple fields in the input modal nicely, so you can have a few different named arrays or other types per object within the top level array.
Apr 22, 2022, 6:02 PM
Chatting with
user A
about this on the side. In case you just meant just creating the desired output with a query:

If I understand the question, this is a bit different from the ‘arrays inside arrays’ limitation. It sounds like they want to change this:
```*[_type == 'presentation'][0]{
projects[]-> {
'presentationSlides': presentationSlides[].images,
},
}```
to something like this:
```*[_type == 'presentation'][0]{
'presentationSlides': projects[]->presentationSlides[].images,
}```
I haven’t tested the above but believe it would do what they’re after.
Apr 22, 2022, 6:24 PM
user M
This gives me
null
for each elements in the array.
Apr 22, 2022, 7:16 PM
user U
Thanks for testing this out. The solution you shared give me the exact same result unfortunately.
Apr 22, 2022, 7:20 PM
user D
I don't have your schema, so it won't be exactly the same. You'll need to apply this logic to your own structure.
Apr 22, 2022, 7:21 PM
That's the issue. It seems that you have a single image in each
presentationSlide
. For me I have an array of images. I don't understand at this point how to get only the url of each image in the array.
Apr 22, 2022, 7:24 PM
Just a few tests here: https://cln.sh/OHIsUV I don't get why if I change it to
images[].asset->url
it takes all the content and put it in the array above.
Apr 22, 2022, 7:30 PM
If you change
image
to
images[]
in Racheal’s snippet, do you get what you’re after at the level you want it?
Apr 22, 2022, 7:36 PM
He'll get a flat array, not the url's separated by slide, I believe.
Apr 22, 2022, 7:36 PM
Yes that's the issue. I get a flat array with 3 objects inside instead of having 2 objects (first one having 2 objects and second one having 1 object).
Apr 22, 2022, 7:39 PM
Ahh, like this then?

*[_type == 'presentation'][0]{
  projects[]->{
    presentationSlides[]{
      'presentationSlides': images[].asset->url
    }
  }
}
Apr 22, 2022, 7:42 PM
Ah that's closer but now it give me an object
presentationSlides
in each object in the array.
(by the way thanks a LOT for helping me crack this one)
Apr 22, 2022, 7:44 PM
Does it have to be an object in each element of the array? Can't it be an array of arrays ? If not this solution is something I could work with.
Apr 22, 2022, 7:46 PM
If not this solution is something I could work with.
Apr 22, 2022, 7:47 PM
I don't think there's any way of getting around having a named field for your array of urls if you want them in separate objects, like in Geoff's query.
Apr 22, 2022, 9:38 PM
The only way I can think might work is to do a naked projection to get the hierarchy you want, and then use the parent operator to break out of that depth for the things you need that are siblings of
presentationSlides
. This might not be performant and I don’t have your schema to confirm, but going from the video you posted you might try something like:

Edit: I just replicated how I think you have your schema, and this doesn’t look like it’ll work.


*[_type == 'presentation'][0]{
  ...,
  'cover': cover.asset->url,
  'slug': slug.current,
  'projects': projects[]->presentationSlides[]{
    'title': ^.title,
    'slug': ^.slug.current,
    'client': ^.projects[]->client->{
      title,
      'slug': slug.current,
    },
    'presentationSlides': images[].asset->url
  }
}
Apr 22, 2022, 10:07 PM
That said, the more I look at it, the more I think my colleagues who work on GROQ would cringe.
Apr 22, 2022, 10:08 PM
Alex is going to read this and just start crying
Apr 22, 2022, 10:43 PM
That’s who I was thinking of. 😅
Apr 22, 2022, 10:43 PM
Oh. I surely don't want to make anyone cry about it. The last solution you shared
user A
is mixing my data not the right way. I'm setting a list of presentationSlides in each projects. And in each slide I have an array of images.
So the array of images is part of the array of slide. And this slide is part of an array in the project. If you want I could share my entire schema.
Apr 23, 2022, 6:21 AM
export default {
  title: "Projects",
  name: "project",
  type: "document",
  initialValue: {
    theme: "light",
    priority: "medium",
  },
  groups: [
    {
      title: "Project Description",
      name: "projectDescription",
    },
    {
      title: "Case Study",
      name: "caseStudy",
    },
    {
      title: "Presentation",
      name: "presentation",
    },
  ],
  fields: [
    {
      title: "Cover",
      name: "cover",
      type: "image",
      group: "projectDescription",
    },
    {
      title: "Project Title",
      name: "title",
      type: "string",
      group: "projectDescription",
    },
    {
      title: "Project Slug",
      name: "slug",
      type: "slug",
      options: {
        source: "title",
      },
      group: "projectDescription",
    },
    {
      title: "Client",
      name: "client",
      type: "reference",
      to: [{ type: "client" }],
      group: "projectDescription",
    },
    {
      title: "Theme",
      name: "theme",
      type: "string",
      options: {
        list: [
          { title: "Light", value: "light" },
          { title: "Dark", value: "dark" },
        ],
      },
      group: "projectDescription",
    },
    {
      title: "Priority",
      name: "priority",
      type: "string",
      options: {
        list: [
          { title: "High", value: "high" },
          { title: "Medium", value: "medium" },
          { title: "Low", value: "low" },
        ],
      },
      group: "projectDescription",
    },
    {
      title: "Tags",
      name: "tags",
      type: "array",
      of: [
        {
          type: "reference",
          to: [{ type: "tag" }],
        },
      ],
      group: "projectDescription",
    },
    {
      title: "Blocks",
      name: "blocks",
      type: "array",
      group: "caseStudy",
      of: [
        {
          title: "Text Block",
          name: "textBlock",
          type: "document",
          initialValue: {
            title: "Text block",
          },
          fields: [
            { title: "Title", name: "title", type: "string" },
            {
              name: "text",
              title: "Text",
              type: "array",
              of: [{ type: "block" }],
            },
            {
              title: "Start",
              name: "start",
              type: "number",
            },
            {
              title: "Width",
              name: "width",
              type: "number",
            },
          ],
        },
        {
          title: "Gallery",
          name: "gallery",
          type: "document",
          initialValue: {
            title: "Gallery",
          },
          fields: [
            { title: "Title", name: "title", type: "string" },
            {
              title: "Images",
              name: "images",
              type: "array",
              of: [{ type: "image" }],
            },
          ],
        },
      ],
    },
    {
      title: "Presentation Slides",
      name: "presentationSlides",
      type: "array",
      group: "presentation",
      of: [
        {
          title: "Slide",
          name: "slide",
          type: "document",
          initialValue: {
            title: "Slide",
          },
          fields: [
            {
              title: "Title (Not visible on the website)",
              name: "title",
              type: "string",
            },
            {
              name: "images",
              title: "Images",
              type: "array",
              of: [{ type: "image" }],
            },
          ],
        },
      ],
    },
  ],
};
Apr 23, 2022, 6:21 AM
export default {
  title: "Presentations",
  name: "presentation",
  type: "document",
  fields: [
    {
      title: "Title",
      name: "title",
      type: "string",
    },
    {
      title: "Slug",
      name: "slug",
      type: "slug",
      options: {
        source: "title",
      },
    },
    {
      title: "Cover",
      name: "cover",
      type: "image",
    },
    {
      title: "Intro",
      name: "intro",
      type: "text",
    },
    {
      title: "Projects",
      name: "projects",
      type: "array",
      of: [
        {
          type: "reference",
          to: [{ type: "project" }],
        },
      ],
    },
  ],
};
Apr 23, 2022, 6:21 AM
Hi all! Your challenge here is that
[]
is a flattening operator, so any kind of expression like
array[].nestedArray[]
will cause the inner array to be flattened out.
You should be able to use this workaround. It’s not pretty, but I think it should work for you:

*[_type == 'presentation'][0]{
  projects[]-> {
    'presentationSlides': presentationSlides[] {
      'urls': images[]->url
    }.urls
  },
}
This “escapes” the flattening by doing the image-to-URL mapping inside an object, and then unwrapping it.
Apr 25, 2022, 10:27 AM
Ah that's exactly what I was looking for. Thanks a lot
user L
. You forgot
.asset
so just for reference this is what worked:
*[_type == 'presentation'][0]{
  projects[]-> {
    'presentationSlides': presentationSlides[] {
      'urls': images[].asset->url
    }.urls
  },
}
Apr 25, 2022, 10:54 AM
Ah, of course, sorry. 👍
Apr 25, 2022, 10:59 AM

Sanity– build remarkable experiences at scale

Sanity is a modern headless CMS that treats content as data to power your digital business. Free to get started, and pay-as-you-go on all plans.

Was this answer helpful?