Ordering Celebs by their most recently updated facts in Sanity.io

12 replies
Last updated: Jun 10, 2022
Hi! I'd like to know how to order values by a referenced field.
I have the document type
celeb
. And the document type
fact
. Each
fact
references a
celeb
. I want to list
celebs
ordered by their most recently updated
facts
. So I want to get a list of
celebs
where the
celeb
that just had a
fact
added about them would show up at the top.
I also posted this question on Stackoverflow to keep a record of the answer
https://stackoverflow.com/questions/72564416/sanity-groq-order-by-the-value-of-a-referenced-field
AI Update

This is a classic GROQ challenge! You want to order celebs based on when their related facts were most recently updated. The key is to use a subquery to find each celeb's most recent fact, then sort by that.

Here's the solution from the Stack Overflow thread you posted:

*[_type == "celeb"] {
  _id,
  name,
  "latestFact": *[_type == "fact" && celeb._ref == ^._id] | order(_updatedAt desc)[0]
}
| order(latestFact._updatedAt desc)

How this works:

  1. Query all celebs: *[_type == "celeb"] gets all celebrity documents

  2. Project with subquery: Inside the projection {}, we create a latestFact field that runs a nested query:

    • *[_type == "fact" && celeb._ref == ^._id] finds all facts where the celeb reference matches the current celeb's _id (the ^ operator references the parent document)
    • | order(_updatedAt desc)[0] sorts those facts by most recent first and takes the first one
  3. Sort by the nested field: The outer | order(latestFact._updatedAt desc) sorts all celebs by their most recent fact's update time

This assumes your fact document has a celeb field that's a reference to a celeb document. If your reference field has a different name, just adjust celeb._ref accordingly.

Performance note: This pattern can be expensive on large datasets since it runs a subquery for each celeb. If you need better performance with many documents, consider denormalizing by storing the latest fact timestamp directly on the celeb document and updating it whenever a fact changes (you could automate this with Sanity Functions).

Hi!
I think something along the lines of this should work:


*[_type == 'celeb']{
 ...,
 "latestFact": *[_type == 'fact' && references(^._id)] | order(_updatedAt)[0]._updatedAt
}| order(latestFact)
Hi! Something like:
*[_type == "celeb"] {
  _id,
  name,
  "latestFact": *[_type == "fact" && celeb._ref == ^._id] | order(_updatedAt desc)[0]
}
  | order(latestFact._updatedAt desc)
This assumes that each
fact
has a field called
celeb
which is a ref to the celeb document.
For each celeb, it finds the latest fact. At the end, it sorts all the celebs by the date.
hah!
user L
Comment race condition 😁
The difference between these two answers is that Jørn’s will just fetch the latest timestamp, while mine will include the latest fact.
A slightly different approach if you ever needed a third one 😄 GROQ is flexible. This one doesn't require a sub-query, although it does reorder your facts. You can work around that if needed:
*[_type == "celeb"]{
  facts[]-> | order(_updatedAt desc)
} | order(facts[0]._updatedAt)
user M
That can be a good solution if celebs have a
facts
field; I assumed they didn’t. Also note that this will fetch all facts for each celeb first, even though only the first one is needed to sort. A subquery like this:
*[_type == "fact" && celeb._ref == ^._id] | order(_updatedAt desc)[0]
…will only need to fetch the newest fact for each celeb.
Ah, good catch! I read it the other way around indeed: that a
celeb
references a
fact
. Please disregard the above 🙂
poweranger
user S
any more questions 😅
So much brain power went into answering my question! Thanks everyone, very appreciated!

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?