71 lines
3.9 KiB
Markdown
71 lines
3.9 KiB
Markdown
# sipiq_import_v1.0 — import SIPIQ odpovědí do MongoDB
|
||
|
||
**Verze:** 1.0 · **Datum:** 2026-06-17 · **Studie:** 77242113UCO3002 (ICONIC / DAWN)
|
||
|
||
## Účel
|
||
Import SIPIQ odpovědí (Qualtrics CSV export) do MongoDB `feasibility` tak, aby šlo:
|
||
1. **křížově analyzovat** „otázka × otázka" (ploché `answers{}` keyed by Qcode),
|
||
2. **zrekonstruovat kompletní SIPIQ** jako v prázdném PDF, jen vyplněný (slovník otázek
|
||
se sekcemi / pořadím / popisky podčástí / typem / options).
|
||
|
||
## Vstup
|
||
Qualtrics **CSV** export (Download a data table → CSV, *Download all fields*, *Export labels*,
|
||
desetinná **tečka** = NEzaškrtnuto „Use commas for decimals"). CSV má 3 hlavičkové řádky:
|
||
- ř.1 = Qcode (Q2, Q6_4, Q31#1_1 …)
|
||
- ř.2 = **text otázky** (legenda)
|
||
- ř.3 = `{"ImportId":"QID…"}` = QID kód shodný s XML exportem (most XML↔CSV)
|
||
|
||
XML export NEobsahuje text otázky (jen QID tagy) → proto importujeme z CSV.
|
||
|
||
## Dvě kolekce v `feasibility`
|
||
### `sipiq_questions` — slovník dotazníku (1 dok = 1 logická otázka)
|
||
`{_id=Qcode báze (Q63), order, qnum, section, qids[QID…], text, type, items[{key,qcode,qid,label}], options[]}`
|
||
- `type`: `single_or_text` | `yesno` | `numeric` | `matrix_yesno` | `matrix_percent` | `matrix`
|
||
- `items[]` = podčásti (řádky matic, části %, kontaktní pole) v pořadí; `key` = sanitizovaný Qcode (`#`/`.`→`_`)
|
||
- `options[]` = odvozené z pozorovaných hodnot (yes/no a single-choice)
|
||
- Idempotentní `replace_one(upsert)`. Stav 17JUN2026: **56 otázek** (27 vícedílných).
|
||
- **STEM_OVERRIDE**: u maticových otázek (Q31/Q63/Q64/Q69) Qualtrics v CSV hlavičce text ořezává „…",
|
||
proto plné znění doplněno z prázdného SIPIQ PDF.
|
||
|
||
### `sipiq_responses` — 1 dok = 1 odpověď
|
||
- `_id` = **Qualtrics ResponseId** (`R_…`, unikátní, stálý)
|
||
- identita centra/PI povýšená nahoru (`site_*`, `pi_*`, `sdl_site_id`, `fire_*`, `mailinglist_id`,
|
||
`recipient_*`) → queryable
|
||
- `meta{}` = dates, status, progress, finished, duration, jazyk, kanál, IP, geo, survey date/time
|
||
- `answers{}` = **plochá mapa** Qcode→hodnota (`answers.Q37_1`, `answers.Q63_1_1`) — jádro pro křížovou analýzu
|
||
- `is_full_sipiq`, `interested` (Q25) pro pohodlí
|
||
- **`investigator_oid`** = ObjectId ref na `feasibility.investigators` (+`investigator_match` = jak)
|
||
- delta bookkeeping: `content_sha256`, `source_file`, `first_imported_at`, `last_seen_at`,
|
||
`last_updated_at`, `history[]`
|
||
|
||
## Delta import (přepíše JEN změněná data)
|
||
- nová odpověď → INSERT
|
||
- existuje, beze změn (shodný `content_sha256`) → aktualizuje pouze `last_seen_at`
|
||
- existuje, změna → `$set` jen změněných polí + `$push` do `history[]` `{changed_at, source_file, changes:[{key,old,new}]}`
|
||
|
||
## Soft-link na investigators (nedestruktivní)
|
||
1. `pi_email` == `email`/`email2` (lowercase), 2. `recipient_email`, 3. fallback příjmení
|
||
(bez diakritiky) + země. Reportuje napárování + KROK. **investigators se NEMĚNÍ.**
|
||
|
||
## Použití
|
||
```
|
||
.venv\Scripts\python.exe Feasibility\sipiq_import_v1.0.py --csv "<cesta.csv>" --dry-run
|
||
.venv\Scripts\python.exe Feasibility\sipiq_import_v1.0.py --csv "<cesta.csv>" --apply
|
||
```
|
||
`--scope czsk` (default, jen CZ+SK) | `--scope all` (všech 276). Mongo 192.168.1.76:27017, bez auth, pymongo.
|
||
|
||
## Stav 17JUN2026 (ostrý běh proveden)
|
||
- `sipiq_questions`: 56 · `sipiq_responses`: 15 (CZ 8 + SK 7)
|
||
- **soft-link 15/15 přes e-mail, všech 15 = KROK 7** (validace: vyplněné SIPIQ = naši KROK-7 investigátoři)
|
||
- `investigator_oid` uložen jako ObjectId → připraveno na `$lookup`
|
||
|
||
## Dotazy (příklady)
|
||
```js
|
||
// křížově: kdo očekává problémy s náborem A má >X eligible
|
||
db.sipiq_responses.find({"answers.Q33":"Yes"}, {pi_last_name:1,"answers.Q37_1":1})
|
||
// join s evidencí investigatora
|
||
db.sipiq_responses.aggregate([{$lookup:{from:"investigators",localField:"investigator_oid",
|
||
foreignField:"_id",as:"inv"}}])
|
||
// rekonstrukce SIPIQ: seřaď sipiq_questions dle order, pro každou otázku/item vezmi answers[key]
|
||
```
|