Troubleshooting unique year values query in Next.js Sanity project.

16 replies
Last updated: Apr 26, 2023
Is it possible to get unique years value only from date time field across all documents of certain type? I have this query
{"uniqueYears": array::unique(

*[_type in ["event", "exhibition"] && defined(endDate)][].endDate

)}
but it returns the unique full dates.

0:"2018-01-06T12:30:00.000Z"

1:"2018-01-13T08:00:00.000Z"
Tried adding
| split("-")[0]
in the end of the query, but it’s not supported.
AI Update

Yes! You can extract unique years from datetime fields in GROQ. The key is to convert the datetime to a string first, then use string::split() to extract the year portion. Here's the working solution:

{
  "uniqueYears": array::unique(
    *[_type in ["event", "exhibition"] && defined(endDate)]
      .endDate
  ) | [string::split(string(@), "-")[0]]
}

How this works:

  1. The filter *[_type in ["event", "exhibition"] && defined(endDate)] gets your documents
  2. .endDate extracts just the endDate values from each document
  3. array::unique() removes duplicate datetime values
  4. The pipe operator | passes the unique datetimes to the next operation
  5. The projection [...] applies a transformation to each element in the array
  6. string() function converts each datetime to a string in RFC3339 format (like "2018-01-06T12:30:00.000Z")
  7. string::split(string(@), "-") breaks the string at each "-" character, creating an array like ["2018", "01", "06T12:30:00.000Z"]
  8. [0] grabs just the first element (the year)

This will give you:

{
  "uniqueYears": ["2018", "2019", "2020"]
}

Alternative approach - You can also apply the transformation before uniquifying:

{
  "uniqueYears": array::unique(
    *[_type in ["event", "exhibition"] && defined(endDate)]
      .[string::split(string(endDate), "-")[0]]
  )
}

Why your original approach didn't work:

  1. The split() function needs the string:: namespace prefix in GROQ
  2. It only works on strings, so your datetime endDate field needs to be converted first using string()
  3. The syntax for applying transformations across arrays requires proper use of projections with []

The years will be returned as strings. If you need them as numbers for sorting or comparison, you'd need to handle that conversion in your application code since GROQ doesn't have a built-in string-to-number conversion function.

Basically get an array of [‘2023’,‘2022’,…‘2004’]
array::unique(
  *[_type in ["event", "exhibition"] && defined(endDate)]{
    "endDate": string::split(endDate, '-')[0]
  }.endDate
)

☝️ Try that?
Was just about to write i figured the query,
{

"uniqueYears": array::unique(

*[_type in ["event", "exhibition"] && defined(endDate)]{

'yearOnly': string::split(endDate, "-")[0],

}[].yearOnly

)

}
But nextjs is not happy with the query 😄
ClientError: expected '}' following object body
Does it work if you normalize the quotation marks in the query? Not sure if that’s a red herring .
Sounds like the query escaped at the wrong place or something
For some reason not
Does it work if you don’t wrap the query in an object?
array::unique(
      *[_type in ["event", "exhibition"] && defined(endDate)]{
        'yearOnly': string::split(endDate, "-")[0],
      }[].yearOnly
    )

Now it’s confused,
ClientError: unable to parse entire expression
Sounds like there is a character error somewhere
im using next-sanity. weirdly in Vision it returns the right output
“result”:*{*_1 item_“uniqueYears”:*[*_6 items_
0:“2019”
1:“2018"
2:“2021”
3:“2022"
4:“2023”
5:“2020"

]
}
user Y
Issue is next-sanity version. Project is using
"next-sanity": "0.6.0"
and just tested on an other project using
"next-sanity": "^4.1.7"
and works as expected!!
User, thanks for looking into this
Aha! Great!
This opens a can of worms now 🤦

Sanity – Build the way you think, not the way your CMS thinks

Sanity is the developer-first content operating system that gives you complete control. Schema-as-code, GROQ queries, and real-time APIs mean no more workarounds or waiting for deployments. Free to start, scale as you grow.

Was this answer helpful?