Sort documents by string field in Sanity desk

10 replies
Last updated: Mar 10, 2022
for example: i have a document called product, and I store a vendor name as a string as product.vendor – I want to sort by this in the desk so i can group all products by their vendors
AI Update

You can sort and group documents in Sanity Studio's Structure Tool by using the Structure Builder API with custom document lists. Here's how to group your products by vendor:

You can create a custom structure that sorts documents by the vendor field using the .defaultOrdering() method on document lists. In your sanity.config.ts (or structure/index.ts), you can set up something like this:

import {defineConfig} from 'sanity'
import {structureTool} from 'sanity/structure'

export default defineConfig({
  // ... other config
  plugins: [
    structureTool({
      structure: (S) =>
        S.list()
          .title('Content')
          .items([
            S.listItem()
              .title('Products by Vendor')
              .child(
                S.documentList()
                  .title('Products')
                  .filter('_type == "product"')
                  .defaultOrdering([{field: 'vendor', direction: 'asc'}])
              ),
            // ... other items
          ])
      })
  ]
})

The key part is .defaultOrdering([{field: 'vendor', direction: 'asc'}]) which will sort all products alphabetically by their vendor name.

If you want to take it further and actually group products into separate lists by vendor (not just sort them), you can use the dynamically group list items with a GROQ filter approach to create separate list items for each vendor.

Alternatively, you can define sort orders directly in your product schema using the orderings property as shown in the Sort Orders documentation:

{
  name: 'product',
  type: 'document',
  fields: [
    {
      name: 'vendor',
      type: 'string',
      title: 'Vendor'
    },
    // ... other fields
  ],
  orderings: [
    {
      title: 'Vendor A-Z',
      name: 'vendorAsc',
      by: [{field: 'vendor', direction: 'asc'}]
    },
    {
      title: 'Vendor Z-A',
      name: 'vendorDesc',
      by: [{field: 'vendor', direction: 'desc'}]
    }
  ]
}

This will give editors a dropdown option to sort by vendor when viewing the product list in Studio. The Structure Builder approach with defaultOrdering makes it the default sort, while the schema orderings approach gives users the flexibility to choose different sort options.

Show original thread
10 replies
i have something like this where i need to add the ability to sort by the string value
  .child(product =>
    S.documentList()
      .title('Products')
      .menuItems(S.documentTypeList('product').getMenuItems())
      .filter('_type == $type')
      .params({type: 'product'}),
i want to group them by vendor – vendor is a string field on the product document (synced from Shopify)
Got it! It'll be really similar to how posts are grouped by author in this example , but since vendor isn't a type itself we'll have to tweak it a bit. Do you have an array that contains all of the possible vendors or would that be something we have to handle inside of the list as well?
I don’t – I have a list of vendor documents elsewhere but they are not necessarily bound to the vendor strings that are returned from Shopify
That does make it more complicated, but not impossible. We'll have to do some GROQ/JS magic. Let me mock something up this afternoon and see if I can get the basics worked out!
so these strings only live on the product
understood – glad it wasn’t something obvious i was missing! hugely appreciate the help 🙂
This one was quite fun to work through! I tend to separate things like this into their own files that I can then import into my main desk structure. First, I fetch an array of all of the different possible strings in the
vendor
field in my
product
documents, then remove the duplicates and map over them.
//productsByVendor.js

import S from '@sanity/desk-tool/structure-builder';
import client from "part:@sanity/base/client"

const sanityClient = client.withConfig({apiVersion: '2021-03-25'})

export default S.listItem()
  .title('Products by Vendor')
  .child(async () => {
    const vendors = await sanityClient
      .fetch(`*[_type == 'product' && vendor != null].vendor`)
      .then((allVendors) => [...new Set(allVendors)]);
    return S.list()
      .title('Products by Vendor')
      .items([
        ...vendors.map((vendor) =>
          S.listItem()
            .title(vendor)
            .child(
              S.documentList()
                .title(vendor)
                .filter('_type == "product" && vendor == $vendor')
                .params({ vendor })
            )
        ),
      ]);
  });

this is very impressive, can’t thank you enough
user M
!
You're welcome and sorry we missed your question originally!

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?