В этой статье продолжаем борьбу с фильтрами по дате в Apache Superset. Сегодня разберем, как реализовать подобие логики remove_filter в старых версиях (до 5), чтобы виртуальный датасет не оборачивался фильтрами.

Обязательно прочитайте первую часть, чтобы понимать, откуда взялись на дашборде фильтры и почему они именно такие.

Довольно часто мы используем виртуальные датасеты. И порой бывает нужда как-то покастомить ту дату, которую передают фильтры. Давайте же сразу наиграем такой кейс:

  • Создаем виртуальный датасет запросом

select *
from messages
where 1=1
and ts > (TIMESTAMP '{{ from_dttm | default("1970-01-01", true) }}' + INTERVAL '3 days')

Предположим что нам, например, крайне важно к той дате, которую пользователь передал в фильтре, добавлять еще 3 дня.

  • Добавляем его на дашборд с фильтром в простой чарт "таблица" и добавляем какую-ту фильтрацию, например last week

Ну и видим боль - виртуальный датасет сверху все равно оборачивается условиями из фильтра. И это не никак не отменить, в отличие от других макросов, где есть параметр remove_filter.

Можно привести целую массу кейсов, почему это плохо. В нашем случае - фильтрация будет работать неверно, ведь мы кастомим, добавляя 3 дня, а суперсет сверху оборачивает эти условия так, что наш кастом работать будет неверно (нет условия на + 3 дня).

Рассмотрим универсальный на все случаи жизни хак.

  • Сперва смотрим, что возвращает макрос, если в фильтр ничего не передано и передано хоть что-то. Для этого в датасете меняем логику, оставляя только select {{from_dttm}} as res. Результаты:

Когда ничего не передано
Когда ничего не передано
Когда что-то передано
Когда что-то передано

Видим, что если ничего не передано - None (именно питонячий None), в противном случае возвращает дату. Имея эту информацию делаем следующее:

  • Перехватываем то, что передано в фильтр, записываем в переменную from_dttm_fv, если в фильтр ничего не передано - записываем 1970-01-01 00:00:00. Далее кастуем это в TIMESTAMP и делаем из этого фиктивную колонку.

{% set from_dttm_fv = from_dttm | default("1970-01-01 00:00:00", true) %}
SELECT *, '{{ from_dttm_fv }}'::TIMESTAMP as fict_column
FROM messages

  • Теперь фиктивную колонку нужно синкнуть в датасет и дать ей разрешения (если вдруг они не дадутся)

Видим, что fict_column теперь является частью датасета, причем с типом DATETIME. Именно для этого крайне важен был каст в TIMESTAMP, и крайне важно было то, какое дефолтное значение возвращает макрос, ведь по умолчанию он возвращает None, и для обхода None мы и добавляли | default("1970-01-01 00:00:00", true). Теперь мы можем фиктивную колонку использовать в фильтрах на дашборде, а так как она имеет тип DATETIME - то и в фильтре TIME COLUMN тоже:

Видим, что мы перехватили значение фильтра, и оно точно будет удовлетворять обоим условиям, которыми суперсет оборачивает наш виртуальный датасет, так как мы берем именно from_dttm, т.е. наименьшее значение. Верхний диапазон to_dttm будет всегда выше. Поэтому оба внешних условия будут истинны. Ну а мы теперь вольны использовать перехваченное значение как угодно. Кстати, давайте и to_dttm тоже перехватим для приличия и покрутим, как нам угодно:

{% set from_dttm_fv = from_dttm | default("1970-01-01 00:00:00", true) %}
{% set to_dttm_fv = from_dttm | default("1970-01-01 00:00:00", true) %}
SELECT *
, '{{ from_dttm_fv }}'::TIMESTAMP as fict_column
FROM messages
WHERE ts > (TIMESTAMP '{{ from_dttm_fv }}' + INTERVAL '3 days')
and ts < (TIMESTAMP '{{ to_dttm_fv }}' + INTERVAL '3 days')

Ну и в результате на дашборде получим следующее:

Видим, что теперь мы вольны что угодно делать со значениями из фильтра, при этом внешние условия будут выполняться.

Примерно так выглядит типичный процесс настройки виртуального датасета:

  1. Плачешь

  2. Гуглишь, читаешь документацию

  3. Пробуешь сделать

  4. Снова плачешь

  5. Начинаешь немного понимать, что происходит

  6. Танцуешь с бубном

  7. PROFIT (непонятно, почему заработало, но тебе уже все равно)

Ну а если хотите понимать суперсет еще лучше и танцевать с бубном без слез (НЕ танцевать с бубном просто не получится) - добро пожаловать на курс автора статьи. По промокоду HABR_BEST предоставляется скидка 30% - Apache Superset: полный курс