Adding custom objects to GROQ query results and sorting them

12 replies
Last updated: Jun 24, 2024
is it possible to add a custom record/object into a query result...I'm building an index of pages for a "resource center" page and at least one of the items that I need in this index lives in a hard-coded Remix route. Currently, I'm doing the sorting in the groq query itself, so I was hoping I could just inject a new item and then use orderBy before sending that to my Remix loader. Otherwise, I'll have to do some array manipulation first before sending it to the client, which isn't the end of the world, but I'm just curious.
AI Update

Unfortunately, you cannot inject custom objects directly into a GROQ query result and sort them together with your Sanity documents. GROQ parameters (using $ syntax) only support JSON literal values - they can't be used to merge custom objects into query results. The spread operator (...) in GROQ is specifically for field projections in objects, not for array concatenation or manipulation.

Since GROQ can't handle this, you'll need to do the array manipulation in your Remix loader code instead. Here's a clean approach:

// In your Remix loader
export async function loader() {
  const query = `*[_type == "resource"] | order(title asc)`;
  const sanityResources = await client.fetch(query);
  
  const customResource = {
    _type: 'resource',
    title: 'Hard-coded Route',
    slug: { current: '/your-remix-route' },
    // other fields matching your resource structure
  };
  
  // Combine and sort
  const allResources = [...sanityResources, customResource]
    .sort((a, b) => a.title.localeCompare(b.title));
  
  return json({ resources: allResources });
}

Alternative approaches to consider:

  1. Create it as an actual Sanity document: Even if it's for a hard-coded route, you could create a resource document in Sanity and just reference the static route in the slug field. This keeps all your sorting logic in GROQ and makes it easier for content editors to manage.

  2. Use a singleton document: If this is a one-off special item, you could create a singleton document in Sanity that represents this resource, giving you full GROQ control.

  3. Handle it in your frontend: If sorting client-side is acceptable, you could fetch resources via GROQ and inject/sort the custom item in your React component.

The JavaScript array manipulation approach isn't the end of the world - it's actually quite common when you need to mix CMS content with application-level data. Just make sure your custom object matches the same shape as your Sanity documents so everything works consistently downstream.

I’m not totally certain it’ll work, but I wonder if you can pass the hardcoded value in with a param:
client.fetch('*[_type == '<your-type>']{
  "remixValue": $remixValue,
  //other fields
} | order(remixValue, desc)', { remixValue })
I'm not sure I follow that. Maybe I didn't explain it that well... I want to query for a certain document type. In this case
_type == "resource"
. Then I want to add a new custom "document" to the results as if it were an actual document in the dataset. Then orderBy a common field, such as title. So a regular query might return an array of two resource documents. I want to append a third and then sort them.
One alternative is to just go ahead and create this resource page in the studio, so it has a title and a slug, but I don't want editors to actual edit anything on this particular page. Hence the hard-coded remix route file. I'm just not sure which is better.
If i can't do it in groq, i'll probably remove the orderBy and then append the item in my Remix loader and then do the sorting there before sending it to the client.
Ok, yes I think that’s still possible. This works for me in the default movie db:
Query:
{ 
  "result": [
    ...*[_type == 'movie'][0...10],
    ...$someOtherMovies
   ] | order(title asc)  
}

Params: 
{
  "someOtherMovies": [{
    title: 'A Title',
  }, { title: 'Another Title'}]
}
You should be able to inject your data into a query and sort all in one go.
wow. okay. awesome. thank you!
You’re welcome!
Ah, scratch that, it doesn’t look like it’s actually ordering it. I’ll keep looking.
Oh, no wait, scratch that scratch. It is working 🙂
yeah it's working for me 🙂
anything is possible with groq lol
It’s true 🙂

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?