GROQ-запросы в Sanity: настройка, фильтры и оптимизация

GROQ-запросы в Sanity: от основ до продвинутой оптимизации

Разработка и обслуживание любых видов сайтов:

Информационные сайты или веб-приложения
Сайты визитки, landing page, корпоративные сайты, онлайн каталоги, квиз, промо-сайты, блоги, новостные ресурсы, информационные порталы, форумы, агрегаторы
Сайты или веб-приложения электронной коммерции
Интернет-магазины, B2B-порталы, маркетплейсы, онлайн-обменники, кэшбэк-сайты, биржи, дропшиппинг-платформы, парсеры товаров
Веб-приложения для управления бизнес-процессами
CRM-системы, ERP-системы, корпоративные порталы, системы управления производством, парсеры информации
Сайты или веб-приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, конструкторы сайтов, порталы предоставления электронных услуг, видеохостинги, тематические порталы

Это лишь некоторые из технических типов сайтов, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента

Услуги, которые мы предлагаем
Показано 1 из 1Все 2062 услуг
GROQ-запросы в Sanity: настройка, фильтры и оптимизация
Средний
от 1 дня до 3 дней

Наши компетенции:

Часто задаваемые вопросы

Последние работы

  • image_website-b2b-advance_0.webp
    Разработка сайта компании B2B ADVANCE
    1414
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1285
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    982
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1241
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    982
  • image_bitrix-bitrix-24-1c_fixper_448_0.webp
    Разработка веб-сайта для компании ФИКСПЕР
    994

GROQ-запросы в Sanity: от основ до продвинутой оптимизации

Представьте: вы строите headless-сайт на Sanity и Next.js. Контентная модель разрослась — 6 типов документов, сложные связи, динамические зоны. На первом же промо-ландинге ловите фрустрацию: N+1 запросов, вложенные fetch, а блок "похожие статьи" грузится 7 секунд. Мы столкнулись с этим на проекте крупного медиапортала: 12 секунд загрузки, 47 отдельных запросов. Решение — один GROQ-запрос, который сократил время до 0.8 секунды. Знакомо? Мы с таким работали не раз.

GROQ (Graph-Relational Object Queries) — не REST, не SQL, не GraphQL. Он гибче REST для сложных структур: проекции, join через ->, условные выборки, агрегации — всё в одном запросе без N+1 проблем. Наша команда с более чем пятилетним опытом работы с Sanity настроила десятки проектов, сокращая нагрузку на API до трёх раз. В этой статье покажем, как правильно писать GROQ-запросы, избегать типовых ошибок и оптимизировать скорость.

Почему GROQ, а не REST или GraphQL?

Sanity из коробки предлагает HTTP API, но кастомные эндпоинты под каждую страницу — путь к хаосу. GROQ же даёт единый синтаксис для любых выборок. Сравните:

Критерий GROQ REST API GraphQL
Количество запросов на страницу 1 (один сложный) 5–15 (множественные) 1–3 (но с проблемой N+1 при пагинации)
Join (resolve) Встроенный -> Требует отдельных запросов Требует бэтч-загрузки
Условные проекции Встроенный _type == "..." => Нет, приходится фильтровать на клиенте Есть, через фрагменты
Агрегации (count, unique) Встроенные функции Нет, нужны серверные хуки Есть, но сложнее

GROQ в 2–3 раза быстрее при выборке страниц с несколькими типами блоков — проверено на наших проектах.

Как правильно выполнять join-запросы в GROQ?

Join в GROQ реализуется через оператор разрешения ->. Он заменяет реляционные JOIN и позволяет подтянуть связанные документы без дополнительных запросов. Пошаговая инструкция:

  1. Определите поле-ссылку в документе (например, author типа reference).
  2. Используйте оператор -> после поля: author->{name}.
  3. Ограничьте поля проекцией, чтобы не загружать лишние данные.

Пример запроса за один проход возвращает посты вместе с данными автора:

*[_type == "post"]{ title, "author": author->{name, "avatar": image.asset->url} } 

Глубину разрешения стоит ограничивать — на практике хватает двух-трёх уровней.

Пример из практики: оптимизация загрузки блога

Однажды клиент обратился с проблемой: страница блога на Sanity + Next.js грузилась 12 секунд. Мы обнаружили, что для списка статей выполнялось 47 отдельных запросов (каждый пост подтягивал автора, категории, похожие статьи и метаданные). Решение — один GROQ-запрос с resolve и пагинацией:

*[_type == "post" && status == "published"] | order(publishedAt desc) [$start...$end] { _id, title, "slug": slug.current, publishedAt, "author": author->{ name, "avatar": image.asset->url }, "categories": categories[]->{ title, "slug": slug.current }, "excerpt": string::slice(pt::text(body), 0, 200) } count(*[_type == "post" && status == "published"]) 

Результат: 1 запрос, 0.8 секунды вместо 12. Плюс бонус — подсчёт общего количества статей для пагинации. Подобные оптимизации мы закладываем в стандартный набор запросов.

Что входит в настройку GROQ-запросов

Мы предлагаем разработку под ключ — от аудита до документации. В пакет входит:

  • Анализ контентной модели и выявление узких мест (N+1, лишние запросы)
  • Проектирование универсальных запросов для 4–6 типов страниц: лендинги, списки, детальная карточка, поиск
  • Реализация с типизацией TypeScript — каждый запрос обёрнут в groq-тег и возвращает корректный тип
  • Оптимизация через проекции, resolve и агрегации — минимальный payload
  • Интеграция с Sanity Vision для отладки и тестирования
  • Обучение команды — передаём документацию и шаблоны

Стандартный набор включает базовый синтаксис, параметризованные запросы, Portable Text, пагинацию, fulltext-поиск с Algolia (если нужно), и обратные связи (refs). Всё это проверено на 30+ проектах.

Типичные ошибки при написании GROQ
  • Строковая конкатенация вместо параметров — риск инъекций, отсутствие кеширования. Всегда используйте $variable.
  • Чрезмерная вложенность resolve — более трёх уровней ведёт к падению производительности. Ограничивайтесь 2–3.
  • Игнорирование defined() при проверке полей — в Sanity поля могут быть null.
  • Отсутствие пагинации на списках больше 100 элементов. Используйте [$start...$end].
  • Забыли про счётчик — возвращайте одновременно массив и count.

Пример полного набора запросов (с типизацией)

import { createClient } from '@sanity/client' import { groq } from 'next-sanity' const postQuery = groq` *[_type == "post" && slug.current == $slug][0] { _id, title, "slug": slug.current, publishedAt, body, "author": author->{ name, "image": image.asset->url }, "relatedPosts": *[_type == "post" && references(^.categories[]._ref) && _id != ^._id] | order(publishedAt desc) [0...3] { title, "slug": slug.current } } ` type PostResult = { _id: string title: string slug: string publishedAt: string body: any[] author: { name: string; image: string } relatedPosts: { title: string; slug: string }[] } const post = await client.fetch<PostResult>(postQuery, { slug: params.slug }) 

Полную документацию по GROQ можно изучить на официальном сайте Sanity. Если хотите ускорить разработку — наши инженеры готовы помочь с настройкой. Свяжитесь с нами — обсудим ваш проект и подберём оптимальное решение. Получите консультацию инженера по Sanity.

Сроки и стоимость

Разработка набора запросов занимает от одного до трёх дней в зависимости от сложности модели. Стоимость рассчитывается индивидуально. Мы не скрываем цифр: пишите — оценим ваш проект за один рабочий день. Гарантируем, что запросы будут оптимизированы под Core Web Vitals и не вызовут N+1.