docs(context): глоссарий домена кликстрима
- Зачем: - зафиксировать доменный язык, чтобы метрики дашборда и урок 6 опирались на единые термины. - Что: - добавлен CONTEXT.md: пользователь/визит-сессия/событие, иерархия, почему на демо Users == Sessions. - Проверка: - термины сверены с sql/ddl/dds/30_dds.sql и sql/ddl/dm/40_dm.sql.
This commit is contained in:
+68
@@ -0,0 +1,68 @@
|
|||||||
|
# CONTEXT.md — глоссарий домена
|
||||||
|
|
||||||
|
Доменный язык стенда: как мы называем сущности кликстрима и что под ними
|
||||||
|
понимаем. Один термин — одно имя. Ведётся вместе с `docs/adr/` (см.
|
||||||
|
[ADR-0001](./docs/adr/0001-spec-adr-issue-layout.md)).
|
||||||
|
|
||||||
|
## Сущности
|
||||||
|
|
||||||
|
### Пользователь (user)
|
||||||
|
|
||||||
|
`user_domain_id` (`UUID`) — постоянный идентификатор пользователя (cookie-уровень),
|
||||||
|
переживает отдельные визиты. Источник — `device_events`, привязан к `click_id`.
|
||||||
|
В витринах: `uniqExact(user_domain_id)`.
|
||||||
|
|
||||||
|
### Визит / сессия (visit / session)
|
||||||
|
|
||||||
|
`click_id` (`UUID`) — **визит**: envelope из одного и более событий с общим
|
||||||
|
контекстом device/geo. В DDL `dds.click` описана как «контекст сессии
|
||||||
|
пользователя» (см. [`sql/ddl/dds/30_dds.sql`](./sql/ddl/dds/30_dds.sql)).
|
||||||
|
|
||||||
|
Важно: в источнике **нет отдельного session-таймаута** (как Snowplow
|
||||||
|
`domain_sessionid`). Поэтому в этой модели **сессия ≡ визит ≡ `click_id`** —
|
||||||
|
группа событий под одним идентификатором, а не окно активности по тайм-ауту.
|
||||||
|
Если в будущем понадобится «настоящая» сессия по 30-минутному окну неактивности —
|
||||||
|
это отдельная производная над `user_domain_id` + `event_ts`; на текущих данных
|
||||||
|
она дала бы те же группы (разброс времени внутри `click_id` ≤ 1 мин).
|
||||||
|
|
||||||
|
«Сессию» и «визит» используем как синонимы; в UI предпочитаем «визит», когда важно
|
||||||
|
подчеркнуть, что это не сессия-по-тайм-ауту.
|
||||||
|
|
||||||
|
### Событие (event)
|
||||||
|
|
||||||
|
`event_id` (`UUID`) — отдельное действие пользователя в рамках визита: `pageview`,
|
||||||
|
`click`, `purchase`, `add_to_cart` и т.п. (поле `event_type`). Источник —
|
||||||
|
`browser_events` + `location_events`. В витринах: `count()`.
|
||||||
|
|
||||||
|
## Иерархия
|
||||||
|
|
||||||
|
```
|
||||||
|
user_domain_id (пользователь, постоянный)
|
||||||
|
└── click_id (визит/сессия — 1..N событий с общим device/geo)
|
||||||
|
└── event_id (событие: pageview / click / purchase ...)
|
||||||
|
```
|
||||||
|
|
||||||
|
Здоровые данные дают пирамиду `users ≤ sessions ≤ events`.
|
||||||
|
|
||||||
|
## Почему на демо `Unique Users == Unique Sessions`
|
||||||
|
|
||||||
|
В демо-датасете (`data/*.jsonl`) каждый пользователь имеет **ровно один**
|
||||||
|
`click_id` — связь user↔визит строго 1:1 (проверено: 99 пользователей =
|
||||||
|
99 `click_id` в полном файле). Поэтому `uniqExact(user_domain_id)` и
|
||||||
|
`uniqExact(click_id)` дают одинаковое число.
|
||||||
|
|
||||||
|
Это **свойство конкретного датасета, а не закон модели и не баг расчёта.** В
|
||||||
|
реальных данных пользователь возвращается несколькими визитами, и числа
|
||||||
|
расходятся. Поэтому на дашборде мы **не** показываем две одинаковые KPI-плитки
|
||||||
|
(это читалось бы как ошибка) — вместо дубля идут производные метрики
|
||||||
|
(события на визит, доля визитов с одним событием), а различие «пользователь vs
|
||||||
|
сессия» объясняется текстом урока.
|
||||||
|
|
||||||
|
Синтетический генератор (ветка `feature/data-generator`) проблему не решает, а
|
||||||
|
усугубляет: он штампует свежий `click_id` на каждое событие, и `click_id`
|
||||||
|
вырождается в «событие». См. `generator/KNOWN_ISSUES.md` на той ветке.
|
||||||
|
|
||||||
|
## Слои данных
|
||||||
|
|
||||||
|
`STG → ODS → DDS → DM` — см. [`docs/ARCHITECTURE.md`](./docs/ARCHITECTURE.md).
|
||||||
|
Витрины (`dm.*`) и дашборд Superset строятся на статическом сиде, не на потоке.
|
||||||
Reference in New Issue
Block a user