Get a peek at our latest innovations at Sanity Product Day on Dec 8th →

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.io: Get the most out of your content

Sanity.io is a platform to build websites and applications. It comes with great APIs that let you treat content like data. Free to get started, and pay-as-you-go on all plans. Find out more.