✨Discover storytelling in the AI age with Pixar's Matthew Luhn at Sanity Connect, May 8th—register now

Help with setting initial values for array of references in Sanity schema

32 replies
Last updated: Jun 8, 2022
  "authors": [
    {
      "_type": "reference",
      "_key": "e4072b1d3618",
      "_ref": "1fcfcd8f-db73-40a7-ac74-684a7a97a2e6"
    },
    {
      "_type": "reference",
      "_key": "e2d64d5f79e3",
      "_ref": "5f700b37-47cd-4a0f-b541-2176046ce962"
    }
  ],

How do I groq this?

I tried:

 *[_type == "person"]{
          "authors": {
                "_type": "reference",
                "_ref": _id
            }
          }

But it gives me:
  "authors": [
    {
      "_key": "81f684c7699b7bc2f8d0a3f5d983cd5f",
      "authors": {
        "_ref": "1fcfcd8f-db73-40a7-ac74-684a7a97a2e6",
        "_type": "reference"
      }
    },
    {
      "_key": "1769186994b00072dcb9acc9910880f2",
      "authors": {
        "_ref": "5f700b37-47cd-4a0f-b541-2176046ce962",
        "_type": "reference"
      }
    }
  ]

Tried many groq queries but just cant figure this one out, any help would be appreciated. Thanks
Jun 8, 2022, 7:19 AM
You need to resolve the references, as explained in the documentation or shown in the cheat sheet :
authors[] -> { ... }
Jun 8, 2022, 7:29 AM
The
[]
means
authors
is an array and you want to do that for every item.
->
means resolving the reference to that document.
...
means all fields.
Jun 8, 2022, 7:30 AM
So this means “resolve all authors references and retrieve all their fields.”
Jun 8, 2022, 7:30 AM
Oh I do not want to get the reference of author, I want the groq projection to look exactly like the original one. I should probably explain I am trying to set an initialvalue for the authors field and have folowed along in this sanity video: https://www.youtube.com/watch?v=iR4JVsWF6uo
Jun 8, 2022, 7:33 AM
Oh, sorry I didn’t get that. How does your person schema look like please?
Jun 8, 2022, 7:34 AM
Have you tried:
*[_type == "person"]{
  _key,
  "_type": "reference",
  "_ref": _id
}
Jun 8, 2022, 7:35 AM
import customImage from "../../lib/custom-image";

export default {
    title: "Person",
    name: "person",
    type: "document",
    fields: [
        {
            title: "Name",
            name: "name",
            type: "string",
        },
        customImage({
            title: "Photo",
            name: "photo",
            description: "The portrait for this editor.",
        }),
        {
            title: "Bio",
            name: "bio",
            type: "text",
            description: "A short biography for this editor, to appear in articles, hub pages, etc.",
        },
    ]
};

here is my person schema
Jun 8, 2022, 7:38 AM
I want the groq projection to look exactly like this: 
  "authors": [
    {
      "_type": "reference",
      "_ref": "1fcfcd8f-db73-40a7-ac74-684a7a97a2e6"
    },
    {
      "_type": "reference",
      "_ref": "5f700b37-47cd-4a0f-b541-2176046ce962"
    }
  ],
Jun 8, 2022, 7:40 AM
But this is not valid JavaScript/JSON to begin with. You need at least a wrapping object to have a named key.
Jun 8, 2022, 7:40 AM
Or you want your projection to return an array of persons.
Jun 8, 2022, 7:40 AM
here is the full raw json:
{
  "_createdAt": "2022-06-08T07:16:41Z",
  "_id": "drafts.98b3e8a1-a3ff-4b47-9a5a-a5d567521bed",
  "_rev": "irwkbf-ico-m75-hqn-nybjc022p",
  "_type": "post",
  "_updatedAt": "2022-06-08T07:16:57Z",
  "authors": [
    {
      "_key": "e4072b1d3618",
      "_ref": "1fcfcd8f-db73-40a7-ac74-684a7a97a2e6",
      "_type": "reference"
    },
    {
      "_key": "e2d64d5f79e3",
      "_ref": "5f700b37-47cd-4a0f-b541-2176046ce962",
      "_type": "reference"
    }
  ],
  "date": "2022-06-08T07:16:37.535Z",
  "photos": {
    "_type": "image",
    "customRatio": 0
  }
}
Jun 8, 2022, 7:41 AM
I‘m a little confused, sorry. Your person schema as shown above doesn’t seem to have an array of references, so I don‘t know what you‘re trying to query.
Jun 8, 2022, 7:44 AM
Where did you get that raw JSON from? What does it represent?
Jun 8, 2022, 7:45 AM
Ah here is the authors field:
{
            title: 'Authors',
            name: 'authors',
            type: 'array',
            of: [{
                type: 'reference',
                to: [{type: 'person'}],
                options: {
                    filter: ({ document }) => {
                        const addedAuthors = document.authors
                            .map(p => p._ref)
                            .filter(Boolean)
                        return {
                            filter: '!(_id in $ids)',
                            params: {
                                ids: addedAuthors                        }
                        }
                    }
                }
            }],
            validation: (Rule) => Rule.required(),
            group: 'content'
        },
Jun 8, 2022, 7:46 AM
Ah right. If you query the
authors
field without any projection or resolution, it should return the array as you expect I believe.
Jun 8, 2022, 7:47 AM
Here is the full code for this page so it makes it easier to see what im trying do
import React from 'react'
import sanityClient from 'part:@sanity/base/client'
import { Gift } from 'phosphor-react'
import customImage from '../../lib/custom-image'

import { getIcon } from './filter'

export default {
    name: "post",
    title: "Post",
    type: "document",
    groups: [
        { title: 'Content', name: 'content', default: true },
        { title: 'SEO', name: 'seo' },
        { title: 'Settings', name: 'settings' },
    ],
    initialValue: async () => ({
        date: new Date().toISOString(),
        authors: await sanityClient.fetch(`
          *[_type == "person"]{
              _key,
              "_type": "reference",
              "_ref": _id
            }
        `)
        // authors: [
        //     {
        //         "_key": "18fdc834e74a",
        //         "_ref": "1fcfcd8f-db73-40a7-ac74-684a7a97a2e6",
        //         "_type": "reference"
        //     },
        //     {
        //         "_key": "3e9896fdaed3",
        //         "_ref": "5f700b37-47cd-4a0f-b541-2176046ce962",
        //         "_type": "reference"
        //     }
        // ],
    }),
    fields: [
        {
            name: "title",
            type: "string",
            title: "Title",
            validation: (Rule) => Rule.required(),
            group: 'content'
        },
        {
            title: 'Authors',
            name: 'authors',
            type: 'array',
            of: [{
                type: 'reference',
                to: [{type: 'person'}],
                options: {
                    filter: ({ document }) => {
                        const addedAuthors = document.authors
                            .map(p => p._ref)
                            .filter(Boolean)
                        return {
                            filter: '!(_id in $ids)',
                            params: {
                                ids: addedAuthors                        }
                        }
                    }
                }
            }],
            validation: (Rule) => Rule.required(),
            group: 'content'
        },
        {
            name: "slug",
            type: "slug",
            title: "Slug",
            options: {
                source: "title",
                maxLength: 100,
            },
            validation: (Rule) => Rule.required(),
            group: 'content'
        },
        customImage({
            title: 'Photo',
            name: 'photos',
            group: 'content',
        }),
        {
            name: "date",
            title: "Date",
            type: "datetime",
            validation: (Rule) => Rule.required(),
            group: 'content'
        },
        {
            title: 'Content',
            name: 'content',
            type: 'complexPortableText',
            group: 'content'
        },
        {
            title: 'Overlay header with transparency?',
            name: 'hasTransparentHeader',
            type: 'boolean',
            description:
                'When activated the header will overlay the first content module with a transparent background and white text until scrolling is engaged.',
            group: 'settings'
        },
        {
            title: 'Filters',
            name: 'filters',
            type: 'array',
            description: 'Define what filters are associated with this product',
            of: [
                {
                    title: 'Filter',
                    name: 'filter',
                    type: 'object',
                    fields: [
                        {
                            title: 'Filter',
                            name: 'filter',
                            type: 'reference',
                            to: [{ type: 'filter' }]
                        },
                        {
                            title: 'Which option is this for?',
                            name: 'forOption',
                            type: 'string',
                            options: {
                                list: [{ title: 'All', value: '' }],
                                from: 'options',
                                fromData: { title: 'name' },
                                joinWith: 'values'
                            }
                        }
                    ],
                    preview: {
                        select: {
                            title: 'filter.title',
                            type: 'filter.type',
                            color: 'filter.color.color',
                            forOption: 'forOption'
                        },
                        prepare({ title = 'Untitled', type, color, forOption }) {
                            const displayType = type && type.trim() ? type : 'simple'
                            const option = forOption ? forOption.split(':') : null

                            return {
                                title,
                                subtitle:
                                    option && option.length > 1
                                        ? `${option[0]}: ${option[1]}`
                                        : 'All Variants',
                                media: getIcon(displayType, color?.hex.toUpperCase())
                            }
                        }
                    }
                }
            ],
            options: {
                editModal: 'popover'
            },
            validation: Rule => Rule.unique(),
            group: 'settings'
        },
        {
            title: 'SEO / Share Settings',
            name: 'seo',
            type: 'seo',
            group: 'seo'
        }
    ]
}
Jun 8, 2022, 7:49 AM
the part im working on is the initialvalue property
Jun 8, 2022, 7:50 AM
So you’re trying to have 2 specific authors as an initial value, right?
Jun 8, 2022, 7:51 AM
yup
Jun 8, 2022, 7:53 AM
I want it to eventually get all the new authors I also add
Jun 8, 2022, 7:54 AM
Right.
Jun 8, 2022, 8:02 AM
So I’m not sure how to populate initial references. I’m searching.
Jun 8, 2022, 8:03 AM
The image is populated as a reference indeed.
Jun 8, 2022, 8:06 AM
So what I would do is query your 2 authors or whatever initial documents. And then in JS, pass that structure.
Jun 8, 2022, 8:07 AM
initialValue: () => myDocuments.map(document => ({
  _type: 'reference',
  _ref: document._id
}))
Jun 8, 2022, 8:07 AM
I’m cutting some corners here, sorry.
Jun 8, 2022, 8:09 AM
But basically, I wouldn‘t mess with groq that much.
Jun 8, 2022, 8:09 AM
Interesting, i initially thought it would be some easy groq manipulation that i might be missing. i though i could make the authors properties and objects go into an array to make it look like this:   "authors": [
    {
      "_type": "reference",
      "_key": "e4072b1d3618",
      "_ref": "1fcfcd8f-db73-40a7-ac74-684a7a97a2e6"
    },
    {
      "_type": "reference",
      "_key": "e2d64d5f79e3",
      "_ref": "5f700b37-47cd-4a0f-b541-2176046ce962"
    }
  ]

but looks like its tougher than I thought. Truly appreciate you trying though, thank you
Jun 8, 2022, 8:19 AM
For now I will just set it manually like above instead of trying to fetch the authors through groq.
Jun 8, 2022, 8:22 AM
I think we misunderstood each other. I would still recommend fetching the documents with your client. I just wouldn‘t overthink the structure in the groq query and do it in JS instead.
Jun 8, 2022, 8:25 AM
Will give it a try but am a little confused how i should go about it, is there any examples of something similar?
Jun 8, 2022, 8:34 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?