sanitygroq

How to get just the most recent of all documents


In sanity studio you get a nice list of the most recent version of all your documents. If there is a draft you get that, if not, you get the published one.

I need the same list for a few filters and scripts. The following groq does the job but is not very fast and does not work in the new API (v2021-03-25).

*[
  _type == $type &&
  !defined(*[_id == "drafts." + ^._id])
]._id

A way around the breaking changes in the API is to use length() = 0 in place of !defined() but that makes an already slow query 10-20 X slower.

Does anyone know a way of making filters that consider only the latest version?

Edit: An example where I need this is if I want to see all documents without any categories. Regardless whether it is the published document or the draft that has no categories it shows up in a normal filter. So if you add categories but don't immediately want to publish it will be confusing in the no-categories-list. ,'-)


Solution

  • 100 X improvement on API v2021-03-25 🥳

    The only way I was able to solve this with speed was to first make a projection of the sub-query so it doesn't run once for every non-draft. Then I thought, why not project both sets and then figure out the overlap, and that was even faster! It runs more than 10 x faster than possible on API v1 and 100 x faster than any suggestions for new API.

    {
      'drafts': *[ _type == $type && _id in path("drafts.**") ]._id,
      'published': *[ _type == $type && !(_id in path("drafts.**"))]._id,
    }
    {
      'current': published[ !("drafts." + @ in ^.drafts) ] + drafts
    }
    
    1. First I get both drafts and non-drafts and "store" it in this projection, like a variable-😉-ish
    2. Then I start with my non-drafts - published
    3. And filter out any that has a counterpart in my drafts "variable"
    4. Lastly I add all drafts to the my list of filtered non-drafts