Access array item index in GROQ projection for filtered arrays

4 replies
Last updated: Nov 29, 2025
Is there a way to access the index of an item in an array in it's projection? For example:
someArray[] {
  someCondition => {
    // this is the thing I want, but I also need the next item in the list the user defined
    nextItem: someArray[currentIndex + 1]
  }

  !someCondition => {
    // mark I don't want this
    marker: true
  }
}[marker!=true]
Or, even better:

someArray[someCondition] {
  // Access the item index of the original array before I filtered it
  nextItem: [(index @ in someArray) + 1]
}
Right now it seems like the only way to do this is to deliver the entire array to my front-end and filter it client-side, which is wasteful on bandwidth.

The only bandwidth-friendly way I can do this without an index is to do multiple queries; one for the shape of the array and others for the specific data I want to fetch. But it would still be much better to do it in a single query.

// shape query
someArray[] {
  // we only get the shape of the array here
  _type, someIdentifier
}

// data query
*[someIdentifier] {...}
*[someIdentifier2] {...}
AI Update

Unfortunately, GROQ doesn't have a built-in way to access the current index of an item during array projection. There's no @index operator or similar construct that gives you the position of an element as you iterate through an array.

However, there are several workarounds depending on your use case:

Based on the Sanity Answers thread, the most practical solution is to fetch the array shape alongside your filtered data:

*[_type == "issue"][0] {
  ...articles[someCondition][0],
  "articleInfo": @ {
    ...,
    "arrayShape": ^.articles[] {
      _type, 
      slug,
      _key
    }
  }
}

This gives you the complete ordered array structure, allowing your frontend to determine the next/previous items based on the current item's identifier (_key or slug). While this requires some client-side logic, it's bandwidth-efficient since you're only fetching minimal identifying fields for the full array.

Alternative Approaches

1. Using negative slice indices:

According to the Pipeline Components documentation, GROQ supports negative indices in slices, where -1 refers to the last element:

someArray[-1]  // Last item
someArray[-2]  // Second to last
someArray[2..-1] // From third element to the last

This is useful for accessing items from the end of an array, but doesn't help you get the "next" item during projection.

2. Parent reference with the ^ operator:

Use the @ (current item) and ^ (parent) operators to reference sibling items:

*[_type == "document"] {
  "items": items[] {
    title,
    "allSiblings": ^.items[]._key
  }
}

Though accessing a specific "next" item by index from within the projection remains challenging without knowing the current position.

3. Multiple queries approach:

If you absolutely need to avoid client-side logic, you could structure your data differently or make separate queries for each item, but as you noted, this is less efficient.

Why This Limitation Exists

As noted in the community discussion, relying on array indices for content relationships is generally fragile—if the array order changes between queries, indices become unreliable. GROQ's design encourages using stable identifiers (_key, _id, slug) for relationships instead.

For your use case of linking to the next article in a user-ordered list, the array shape pattern is the most robust solution. It gives you the ordering context you need while maintaining referential integrity through unique identifiers rather than positional indices. You fetch the minimal array structure (just identifiers) alongside your detailed data, then handle the next/previous logic client-side with the stable ordering information.

This approach is bandwidth-efficient because you're only including lightweight identifiers for the full array, not the complete content of every item. Your frontend can then match the current item's _key or slug in the array shape to determine its neighbors—which is safer than relying on numeric indices that could shift between queries.

Show original thread
4 replies

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?