QQL (Quevell Query Language) это язык, на котором задаются вопросы о задачах: в поиске, в сохраненных фильтрах, на досках и в условиях правил автоматизации. Везде один и тот же язык с одним и тем же разбором: запрос, работающий в поиске, дословно работает в условии правила.
Тому, кто пишет на JQL, синтаксис знаком: =, in, ~, and, order by означают то, что вы ожидаете. Намеренно в языке нет предикатов по истории (was, changed). Время выполнения запроса предсказуемо и не зависит от формулировки: у каждого оператора известная стоимость.
Синтаксис
Запрос это условие и, при желании, сортировка:
status = "In progress" and assignee = currentUser() order by updated desc
- Условия соединяются
andиor, группируются скобками, отрицаютсяnot. - Регистр не важен:
Status,statusиSTATUSэто одно поле,ANDиandэто один союз. - Пустота проверяется словами:
dueDate is empty,assignee is not empty. Записать пустоту как равенство "ничему" нельзя, и это намеренно. - Списки значений:
status in ("To do", "In progress"),assignee not in (anna@example.com, ivan@example.com). - Запрос из одной сортировки тоже запрос:
order by updated descозначает "все, что мне видно, свежее сверху".
Запрос возвращает только то, что видит выполняющий его пользователь: задачи из проектов, которые вам не видны, не существуют для вашего запроса. Это относится и к правилам автоматизации: условия правила выполняются с правами аккаунта, от имени которого работает правило.
Операторы
| Оператор | Смысл |
|---|---|
= , != | Равно, не равно |
in , not in | Входит в список, не входит |
~ | Содержит текст |
is empty , is not empty | Пусто, не пусто |
> >= < <= | Сравнение чисел, дат и длительностей |
Не каждый оператор применим к каждому полю: у даты нет ~, у текста нет >. Такой запрос не выполняется "в никуда", а отклоняется при разборе с указанием места и списка операторов, которые поле принимает. Полный перечень: в таблицах ниже.
Приоритет операторов
not сильнее and, and сильнее or. Запрос a or b and c означает a or (b and c). Скобки всегда важнее: (a or b) and c.
Кавычки и экранирование
Значение с пробелами или служебными символами берется в кавычки, двойные или одинарные: status = "In progress", summary ~ 'новый офис'. Внутри кавычек нет экранирования: строка с двойными кавычками берется в одинарные и наоборот. Значения без пробелов пишутся как есть: OFFICE-13, -7d, 2026-08-24, anna@example.com.
Значения перечислимых полей распознаются по любому написанию: ключу, названию по умолчанию и каждому переводу. status = "В работе" и status = "In progress" это один запрос: значение превращается в неизменный ключ, и фильтр переживает переименование статуса.
Системные поля
Таблица генерируется из кода продукта и не может от него отстать.
| Поле | Операторы | Сортировка |
|---|---|---|
archived | = != | нет |
assignee | = != in not in is empty is not empty | нет |
created | > >= < <= | да |
description | = != ~ is empty is not empty | нет |
dueDate | is empty is not empty > >= < <= | да |
key | = != in not in | да |
level | = != in not in | нет |
originalEstimate | = != is empty is not empty > >= < <= | да |
parent | = != in not in is empty is not empty | нет |
priority | = != in not in is empty is not empty | да |
project | = != in not in | да |
remainingEstimate | = != is empty is not empty > >= < <= | да |
reporter | = != in not in is empty is not empty | нет |
sprint | = != in not in is empty is not empty | нет |
startDate | is empty is not empty > >= < <= | да |
status | = != in not in | нет |
statusCategory | = != in not in | нет |
summary | = != ~ is empty is not empty | нет |
team | = != in not in is empty is not empty | нет |
text | ~ | нет |
timeSpent | = != > >= < <= | да |
type | = != in not in | нет |
updated | > >= < <= | да |
watcher | = != in not in is empty is not empty | нет |
Замечания к отдельным полям:
keyиparentпринимают ключи задач:key in (OFFICE-1, OFFICE-2),parent = OFFICE-13. Регистр ключа не важен.textэто то же, что ищет строка поиска: название и описание вместе. Только~.watcherспрашивает, кто следит за задачей:watcher = currentUser()находит задачи, за которыми следите вы. За одной задачей следят несколько человек, поэтому равенство здесь означает "среди наблюдателей".watcher is emptyнаходит задачи без наблюдателей.teamспрашивает, отмечена ли команда на задаче:team = "Логистика". У одной задачи может быть несколько команд, поэтому равенство здесь означает "содержит".sprintспрашивает, в каком спринте задача:sprint = "Спринт 5". Поле "Спринт" на задаче показывает все ее спринты, закрытые тоже, и запрос читает его так же: задача, которая была в спринте с этим именем, находится и после того, как спринт закрыт.sprint is emptyнаходит задачи, которые не были ни в одном спринте.- Имена спринтов могут повторяться, в разных проектах и в одном.
sprint = "Спринт 5"находит задачи всех видимых вам спринтов с этим именем. Если имя есть в нескольких проектах, подсказка показывает рядом с ним ключ проекта, а в запрос вставляет только имя. Регистр букв не важен, а пробел у края внутри кавычек считается частью имени. statusCategoryпринимает три значения:TODO,IN_PROGRESS,DONE, а также написанияto doиin progress.priorityпринимаетhighest,high,medium,low,lowest.- Архивные задачи запрос находит, только когда спрашивает о них:
archived = trueнаходит только архивные,archived = falseтолько рабочие. Значениядаинетработают так же. - Длительности (
timeSpent,originalEstimate,remainingEstimate) сравниваются в формате учета времени:timeSpent > 1d,originalEstimate <= 2w, где1w= 5 дней,1d= 8 часов. startDateиdueDateэто календарные дни: "срок на этой неделе" означает одно и то же в любом часовом поясе.createdиupdatedэто моменты времени.
Пользовательские поля
Пользовательское поле указывается в запросе по имени: Бюджет > 100000, "Дата запуска" < startOfMonth(). Операторы определяются типом поля:
| Тип поля | Операторы | Сортировка |
|---|---|---|
| Дата | = != is empty is not empty > >= < <= | да |
| Задача | = != in not in is empty is not empty | нет |
| Мультивыбор | in not in is empty is not empty | нет |
| Число | = != is empty is not empty > >= < <= | да |
| Абзац | ~ is empty is not empty | нет |
| Выбор | = != in not in is empty is not empty | да |
| Строка | = != ~ is empty is not empty | нет |
| Ссылка | = != ~ is empty is not empty | нет |
| Пользователь | = != in not in is empty is not empty | нет |
- У числа нет
~: подстрока числа ничего о нем не говорит. У абзаца нет=: точное равенство со страницей текста никто никогда не имел в виду. Многозначный выбор проверяется толькоinиnot in. - Поля определяются в проектах, поэтому одному имени могут соответствовать несколько полей. Запрос по имени охватывает их все, пока они одного типа; имя, которое в одном проекте означает дату, а в другом абзац, ведет себя как текст.
- Запрос хранит неизменные идентификаторы, а не имена: переименование поля или варианта не ломает сохраненный фильтр.
Функции
| Функция | Что означает |
|---|---|
currentUser() | Тот, кто выполняет запрос. В сохраненном фильтре это тот, кто его открыл. |
myReports() | Мои прямые подчиненные по организационной структуре. Без меня самого. |
myVertical() | Все, кто подо мной по структуре, на любую глубину. Без меня самого. |
myTeammates() | Все пользователи из всех команд, где я состою, в любой роли. Без меня самого. |
now() | Текущий момент. |
startOfDay() , startOfWeek() , startOfMonth() | Начало сегодняшнего дня, недели (с понедельника), месяца. |
myReports(), myVertical() и myTeammates() возвращают нескольких пользователей, поэтому используются только с in: assignee in (myReports()). Форма assignee = myReports() отклоняется с подсказкой. "Мои подчиненные и я" записывается так: assignee in (myReports(), currentUser()).
Функции пользователей и времени вычисляются при каждом выполнении, а не при сохранении: фильтр "обновлено за последнюю неделю" каждый раз отсчитывает неделю от момента, когда его открыли. День при этом считается по часовому поясу того, кто спрашивает: для запроса человека по часовому поясу его профиля, для правила по расписанию по часовому поясу правила, а если ни того ни другого нет, по UTC.
Даты и относительное время
Поля дат и моментов сравниваются с:
- фиксированной датой:
duedate <= 2026-09-15; - относительным сдвигом:
updated > -7d(семь дней назад),duedate <= +7d(семь дней вперед); единицыd,w,m: дни, недели, месяцы; - функциями:
created >= startOfMonth(),updated > startOfWeek().
Пользователи
Пользователь указывается по имени или по адресу почты: assignee = "Анна Петрова", assignee = anna@example.com. Если в компании два пользователя с одним именем, запрос по имени отклоняется и просит адрес: тезки в компании бывают, и запрос должен однозначно указать, кого имеет в виду.
Сортировка
order by поле и направление: asc (по умолчанию) или desc. Сортируемость поля указана в таблицах выше; попытка сортировать несортируемое поле отклоняется при разборе. Один ключ сортировки на запрос.
project = OFFICE and status != Done order by duedate asc
Сообщения об ошибках
Ошибка разбора указывает на позицию в запросе и говорит, что именно не так. Типичные сообщения и их смысл:
| Сообщение | Что означает |
|---|---|
Поля с названием "..." нет | Такого поля нет. Проверьте имя; пользовательские поля указываются по имени поля, статусы это значения поля status. |
"..." не поддерживает ~. Оно принимает =, !=, ... | Оператор не применим к полю; список рядом перечисляет применимые. |
Нет значения "..." в поле status | Значение не входит в словарь поля. Если словарь короткий, он приводится тут же. |
Здесь никого не зовут "..." | Пользователь с таким именем или адресом не найден. |
Пользователей с именем "..." несколько (2). Укажите вместо имени адрес почты | Имя неоднозначно; укажите адрес почты. |
"..." не дата. Используйте 2026-08-24, -7d, startOfWeek() или now() | Значение не читается как дата или сдвиг. |
Это не длительность. Используйте вид 1w 2d 4h 30m (1w = 5d, 1d = 8h) | Длительность в другом формате. |
"..." не ключ задачи вида PROJECT-12 | Поле ожидает ключ задачи. |
По "..." нельзя сортировать | Поле не сортируется. |
Кавычка не закрыта | Кавычка открыта и не закрыта. |
myReports() называет нескольких пользователей. Спросите так: "assignee in (myReports())" | Функция возвращает нескольких пользователей и используется только с in. |
Примеры
assignee = currentUser() and status != Done order by duedate asc
Мои незакрытые задачи, ближайшие сроки сверху.
project in (OFFICE, WAREHOUSE) and priority in (highest, high) and status = "In progress"
Горящее в работе по двум проектам.
assignee in (myVertical()) and duedate < startOfWeek() and status != Done
Просроченное у всех, кто подо мной по структуре.
summary ~ "переезд" or description ~ "переезд"
Задачи, где переезд упомянут в названии или описании. То же самое короче: text ~ "переезд".
(assignee = currentUser() or reporter = currentUser() or watcher = currentUser()) and statusCategory != DONE
Все незакрытое, что меня касается: я исполнитель, автор или наблюдатель.
type = Bug and created >= -30d and assignee is empty
Дефекты за месяц, у которых нет исполнителя.
"Бюджет" > 500000 and "Дата запуска" <= startOfMonth()
Пользовательские поля: число и дата.
team = "Логистика" and remainingEstimate > 1w
Задачи команды, где осталось больше недели работы.