How to query span text within block types using GROQ?

24 replies
Last updated: Feb 8, 2022
Hi here, I would like to know how can I get the text of each span within block types using GROQ?
Example:


{
  // ...
  "description": [
    {
      "_key": "1c68d5f6b2a3",
      "_type": "block",
      "children": [
        {
          "_key": "c33a78ff1695",
          "_type": "span",
          "marks": [],
          "text": "A synergistic blend of bioavailable vitamins C & D, herbs, NAC and zinc designed to help improve your long-term immune response."
        }
      ],
      "markDefs": [],
      "style": "normal"
    },
    // ...
  ],
  // ...
}

AI Update

To extract the text from each span within block types using GROQ, you can use array traversal and projection. Here's how:

Basic Text Extraction

To get all the text from spans in a single block content field:

*[_type == "yourDocumentType"] {
  "plainText": description[].children[].text
}

This flattens all the text values from all spans across all blocks into a single array.

Joining Text into a String

If you want to join the text together (similar to the example in the Presenting Portable Text guide):

*[_type == "yourDocumentType"] {
  "plainText": array::join(description[].children[].text, " ")
}

This uses the array::join() function to concatenate all text with spaces between them.

Preserving Block Structure

To maintain the block structure while extracting text from each block separately:

*[_type == "yourDocumentType"] {
  description[] {
    _key,
    _type,
    "text": array::join(children[].text, "")
  }
}

This gives you an array where each block has its combined text.

Filtering by Block Type

To only get text from specific block types (like paragraphs):

*[_type == "yourDocumentType"] {
  "paragraphText": description[_type == "block"].children[].text
}

Complete Example

Based on your example structure, here's a complete query:

*[_type == "product"] {
  _id,
  "descriptionText": array::join(description[].children[].text, " "),
  "descriptionBlocks": description[] {
    _key,
    style,
    "blockText": array::join(children[].text, "")
  }
}

This gives you both a flattened version of all text and a structured version with text per block.

The key pattern is using description[].children[].text to traverse from the block array → into each block's children array → and extract each span's text property. You can then use array::join() to concatenate the strings as needed.

Show original thread
24 replies
I am getting 0 items always
user M
I know that you might have a lot of questions around, but I was wondering if you can help me with this one instead of this , I need a set of products but I can’t get the description easily yet.
The idea is to access to the text of each element of the
children
property
It looks like it’s not working properly on an nested array like this one
Can you try:
"description": description[].children[].text 
No, it don’t work
Are you trying to make each text node its own named field? If so, why?
Good question… 😪 I think I might be doing something wrong, but my intention is to get a JSON file of products with just few props in it, like title, id, description, tags, benefits to use Algolia, but I’m not sure if I am doing something wrong.
Any suggestion would be appreciated
I was thinking in having a single field called
description
with all its texts as a single string value, but I am not sure if this is the right strategy
Got it! I understand now. You'll want to use the built in Portable Text function then. This should convert your description field into plain text:
"description": pt::text(description)
Got it! I understand now. You'll want to use the built in Portable Text function then. This should convert your description field into plain text:
"description": pt::text(description)
user M
Thank you again!
user M
Thank you again!
It did the job.
Interesting, I was using the V1 and it didn’t work either, but reading more about the API Version it enable such outcomes, even some of the old that I was trying.This is now working as an array of string values:

description[].children[][].text,

user M
by the way, is there a way to specify a version for the queries?Currently I have many queries using
V1
and for this case I have to use a different, is that possible?
It looks it’s possible 🤔 I will try
It looks it’s possible 🤔 I will try
Ah, yes, you shouldn't be using
v1
in most cases. In Vision, you can select the one you want to use (usually
v2021-03-25
). When you're query from an external source you can use one of the methods here .
You’re awesome.Thanks again.
By the way,
user M
please, a last question.Do you know if the
v2021-03-25
has backward compatibility with
v1
? if that’s the case I could make an upgrade in our service.
By the way,
user M
please, a last question.Do you know if the
v2021-03-25
has backward compatibility with
v1
? if that’s the case I could make an upgrade in our service.
No worries, I read the docs detailed, it’s super clear.

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?