How to Order and Specifically Select Multiple _Types in a Query

5 replies
Last updated: Mar 10, 2022
I have a pretty specific query I’m trying to call, the purpose of this query is to get the 4 most recent “hikes” and the 1 most recent blog “post”. My query looks like this:
*[_type in ["hikes", "post"]]{
  _type == "hikes" => {
    _createdAt,
    body,
    mainImage,
    number,
    people,
    slug,
    title,
    trailHiked -> {
        name,
        difficulty,
        distance,
        rating,
        trailType,
        location
    }
  },
  _type == "post" => {
    title,
    body,
    mainImage
  }
}
I’m currently using
this resource for selecting multiple types in a query, its working so far but how can I specify the 4 most recent hikes (assuming I use
[0…4]
somewhere) and the most recent post (
[0]
?)?
AI Update

The challenge you're facing is that you need different limits for different document types in a single query. Unfortunately, GROQ doesn't allow you to apply different slice operations ([0...4]) to different document types within a single filter like *[_type in ["hikes", "post"]].

The best solution is to use GROQ's array concatenation operator (+) to combine two separate queries with their own limits and ordering:

*[_type == "hikes"] | order(_createdAt desc) [0...4] {
  _createdAt,
  body,
  mainImage,
  number,
  people,
  slug,
  title,
  trailHiked -> {
    name,
    difficulty,
    distance,
    rating,
    trailType,
    location
  }
} + *[_type == "post"] | order(_createdAt desc) [0] {
  title,
  body,
  mainImage
}

The + operator concatenates the results of both queries into a single array. This gives you exactly what you need: the 4 most recent hikes and the 1 most recent post.

Key points:

  • Each query can have its own order() and slice [0...4] or [0]
  • The + operator merges the results into one array
  • You no longer need the conditional projection syntax (_type == "hikes" => {...}) since each query already filters by type
  • Make sure to add | order(_createdAt desc) to each query to get the most recent documents

If you need the results in a specific order (like all hikes first, then the post), the concatenation order controls that. If you want them sorted together by date after merging, you could wrap the whole thing: (*[_type == "hikes"] | order(_createdAt desc) [0...4]{...}) + (*[_type == "post"] | order(_createdAt desc) [0]{...}) | order(_createdAt desc), though this would mix hikes and posts chronologically.

I think if I were in your situation, I'd use two separate projections wrapped in an object:
`{
  'hikes': *[_type == 'hike'][0...3]{
    _createdAt,
    body,
    mainImage,
    number,
    people,
    slug,
    title,
    trailHiked -> {
        name,
        difficulty,
        distance,
        rating,
        trailType,
        location
    }
  },
  'post': *[_type == 'post'][0]
}`
Oh thats great! I didnt know I could do that
Hmm my hikes portion comes back as an empty array
Hmm my hikes portion comes back as an empty array
ah nevermind it needed to be hikes

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?