Unlock seamless workflows and faster delivery with our latest releases - Join the deep dive

Retrieving previous and next items with GROQ in Sanity.io

14 replies
Last updated: Jun 3, 2021
How can I retrieve with GROQ the previous and next item from the same type, such as a news post?
{
    "post": *[_type == "news" && slug.current == "${page.params.slug}"] [0],
    "prev": "???",
    "next": "???",
}
Jun 2, 2021, 1:53 PM
It is indeed having a date field
Jun 2, 2021, 2:01 PM
I would start with something like this to see if it works for you. You can change
_createdAt
to whichever date field you want (ideally a dateTime, and it will need to be unique). Remove
_id
after the filters if you want to return the whole object.

*[_type == 'news' && slug.current == "${page.params.slug}"][0] {
  ...,
  'prev': *[_type == 'news' && !(_id in path('drafts.**')) && _createdAt < ^._createdAt]._id | order(_createdAt desc)[0],
  'next': *[_type == 'news' && !(_id in path('drafts.**')) && _createdAt > ^._createdAt]._id | order(_createdAt desc)[0]
}
Jun 2, 2021, 2:30 PM
I would start with something like this to see if it works for you. You can change
_createdAt
to whichever date field you want (ideally a dateTime, and it will need to be unique). Remove
_id
after the filters if you want to return the whole object.

*[_type == 'news' && slug.current == "${page.params.slug}"][0] {
  ...,
  'prev': *[_type == 'news' && !(_id in path('drafts.**')) && _createdAt < ^._createdAt]._id | order(_createdAt desc)[0],
  'next': *[_type == 'news' && !(_id in path('drafts.**')) && _createdAt > ^._createdAt]._id | order(_createdAt desc)[0]
}
Jun 2, 2021, 2:30 PM
user A
seems to work pretty well! You're a true genius haha, thanks
Jun 2, 2021, 2:43 PM
Glad it works for you! 🙌
Jun 2, 2021, 2:56 PM
Glad it works for you! 🙌
Jun 2, 2021, 2:56 PM
Alright
user A
, spoke too soon haha. So it does work, but let's say I'm on the post 3 (the oldest from the date field) and want to go to the previous one, it jumps to the first post in date and not the one just before the current one in date if that makes sense
*[_type == "news" && slug.current == "${page.params.slug}"] [0] {
    ...,
    "next": *[_type == 'news' && !(_id in path('drafts.**')) && date > ^.date] | order(date desc) [0],
    "prev": *[_type == 'news' && !(_id in path('drafts.**')) && date < ^.date] | order(date desc) [0]
}
Jun 3, 2021, 8:41 AM
I believe it's because it's taking the first with [0] on
prev
, but I have no clue how to get the one just before 🤔
Jun 3, 2021, 8:44 AM
Just to make sure we’re using the same terms, what do you mean by “the previous one?” If you’re on post 3, and it’s the oldest post, I would expect
prev
to be null.
Jun 3, 2021, 2:22 PM
By previous I mean the one just before according to the date
Jun 3, 2021, 2:38 PM
By previous I mean the one just before according to the date
Jun 3, 2021, 2:38 PM
so let's say we have 2021-04-23, 2020-09-15, 2019-07-21 and I'm on 2019-07-21, I should have 2020-09-15 as my "previous" post
Jun 3, 2021, 2:39 PM
but right now it gets the first of all, so 2021-04-23
Jun 3, 2021, 2:39 PM
K, thank you. It might be a game of playing with your orders (using
asc
instead of
desc
, for example).
Jun 3, 2021, 2:45 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?