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

How to Write a Filter Query

26 replies
Last updated: Jun 8, 2020
Hello amazing Sanity people 🌞 ! I am doing my head in trying to figure out how to write a filter query.I have a document with an array called
primary

primary
is an array of
item
objects.In item, instead of getting a list of all sections, I only want to see those which are not already referenced by my document.
Maybe this is actually very simple, but I can’t seem to work it out…

  name: 'item',
  title: 'Item',
  type: 'object',
  fields: [
    {
      name: 'section',
      title: 'Section',
      type: 'reference',
      to: { type: 'section' },
      options: {
        filter: ({ document, parent, parentPath }) => {
          console.log(document._id)

          return {
            filter: '!(^._id in *[_id==$document].primary[])',
            params: {
              document: document._id
            }
          }
        }
      }
    }
  ]

May 28, 2020, 1:33 PM
Could it be as simple as
!references($document)
?
May 28, 2020, 1:37 PM
I wish! That would only check if
section
has a direct reference to
document
but not if
document
has an array which has a reference to
section
May 28, 2020, 1:39 PM
Running
*[_id==$document][0].primary[].section[]
in Vision gives me
May 28, 2020, 1:43 PM
is
^._id
referring to the potential `section`s
_id
in this case?
May 28, 2020, 1:44 PM
The updated filter is:
^._id in *[_id==$document][0].primary[].section[]
Still not producing any results :'(
May 28, 2020, 1:45 PM
Hm, something tells me you're hitting some array travelsal bug in the query handling. I've seen similar queries failing due to that
May 28, 2020, 1:54 PM
aha
May 28, 2020, 1:54 PM
For what it's worth, it should be
^._id in *[_id==$document][0].primary[].section[]._ref
May 28, 2020, 1:56 PM
(you just want an array of strings)
May 28, 2020, 1:57 PM
Hmm… if I run
*["f6529b36-sectionID" in *[_id==$document][0].primary[].section[]._ref]
I’m just getting every single document in my store
May 28, 2020, 2:01 PM
Very odd
May 28, 2020, 2:02 PM
Because what you sent me does give me an array of strings
May 28, 2020, 2:03 PM
I would have assumed that
*["string" in []]
would produce the right results
May 28, 2020, 2:03 PM
But maybe there is a traversal bug of some sort
May 28, 2020, 2:04 PM
Have you ever tried to filter out a reference that’s already added to a list?
May 28, 2020, 2:13 PM
Would unique validation be of any helo? https://www.sanity.io/docs/array-type#unique()-49ee9907c730
May 28, 2020, 3:58 PM
user C
Just tested this to filter out refs already added to the list, seems to work:


          options: {
            filter: ({document}) => {
              const ids = document.people.map(person => person._ref).filter(Boolean)
              return {
                filter: '!(_id in $ids)',
                params: {ids}
              }
            }
          }
May 28, 2020, 4:09 PM
🙏
May 28, 2020, 4:21 PM
Hero! And all it took was some javascript magic! Thank you so much Jørn! Your second example was perfect… it actually checks the existence in more than one array!
May 28, 2020, 4:22 PM
I ♥️ Sanity
May 28, 2020, 4:23 PM
❤️
May 28, 2020, 4:48 PM
Hi still fiddelng with this is the code below allong the correct lines? Its not working at the moment?
Jun 8, 2020, 2:17 PM
export default {
	name: 'single',
	title: 'Single',
	type: 'document',
	fields: [
		{
			name: 'name',
			title: 'Name',
			type: 'string',
			validation: (Rule) => Rule.required(),
		},
		{
			name: 'tracks',
			title: 'Tracks',
			type: 'array',
			of: [
				{
					type: 'reference',
					to: [{ type: 'track' }],
				},
			],
			options: {
				filter: ({ document }) => {
					const ids = document.track.map((trk) => trk._ref).filter(Boolean)
					return {
						filter: '!(_id in $ids)',
						params: { ids },
					}
				},
			},
			validation: (Rule) => Rule.required(),
		},
	],
}
Jun 8, 2020, 2:17 PM
Think you're missing an s? Should be
document.tracks
?
Jun 8, 2020, 2:55 PM
Thanks good spot
Jun 8, 2020, 6:24 PM
Easy to miss 😅
Jun 8, 2020, 7:00 PM

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?