Help with setting initial values for array of references in Sanity schema
32 replies
Last updated: Jun 8, 2022
P
"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
K
You need to resolve the references, as explained in the documentation or shown in the cheat sheet :
authors[] -> { ... }
Jun 8, 2022, 7:29 AM
K
The
[]means
authorsis 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
K
So this means “resolve all authors references and retrieve all their fields.”
Jun 8, 2022, 7:30 AM
P
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
K
Oh, sorry I didn’t get that. How does your person schema look like please?
Jun 8, 2022, 7:34 AM
K
Have you tried:
*[_type == "person"]{ _key, "_type": "reference", "_ref": _id }
Jun 8, 2022, 7:35 AM
P
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
P
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
K
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
K
Or you want your projection to return an array of persons.
Jun 8, 2022, 7:40 AM
P
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
K
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
K
Where did you get that raw JSON from? What does it represent?
Jun 8, 2022, 7:45 AM
P
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
K
Ah right. If you query the
authorsfield without any projection or resolution, it should return the array as you expect I believe.
Jun 8, 2022, 7:47 AM
P
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
P
the part im working on is the initialvalue property
Jun 8, 2022, 7:50 AM
K
So you’re trying to have 2 specific authors as an initial value, right?
Jun 8, 2022, 7:51 AM
P
yup
Jun 8, 2022, 7:53 AM
P
I want it to eventually get all the new authors I also add
Jun 8, 2022, 7:54 AM
K
Right.
Jun 8, 2022, 8:02 AM
K
So I’m not sure how to populate initial references. I’m searching.
Jun 8, 2022, 8:03 AM
K
So in an example deep in the repo, I found this: https://github.com/sanity-io/sanity/blob/49a07c89ea2e1e56437c47be7cffae75ced5683e/dev/test-studio/schema/author.js#L116
Jun 8, 2022, 8:06 AM
K
The image is populated as a reference indeed.
Jun 8, 2022, 8:06 AM
K
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
K
initialValue: () => myDocuments.map(document => ({ _type: 'reference', _ref: document._id }))
Jun 8, 2022, 8:07 AM
K
I’m cutting some corners here, sorry.
Jun 8, 2022, 8:09 AM
K
But basically, I wouldn‘t mess with groq that much.
Jun 8, 2022, 8:09 AM
P
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
P
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
K
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
P
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.