# 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 "" --dry-run .venv\Scripts\python.exe Feasibility\sipiq_import_v1.0.py --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] ```