Wikipedie:WikiProjekt Překlad/Hledání článků k překladu pomocí WQS

Byla spuštěna webová služba Wikidata Query Service (https://query.wikidata.org), která mimo jiné umožňuje vyhledávat v databázi Wikidata články k překladu podle různých podmínek. Tyto podmínky se zadávají v jazyce SPARQL. Jazyk je to poměrně neznámý, ale na uvedeném webu je mnoho příkladů (Examples) různých dotazů, jimiž se lze inspirovat, pokud se o něm chcete dozvědět více. Pro hledání článků k překladu však by mělo stačit modifikovat a spouštět následující příklady.

Dotaz (kousek programu, začínající slovem SELECT) se zkopíruje do velkého okénka na webu WQS a zmáčkne se tlačítko Run. Pokud program doběhne, zobrazí se tabulka s výsledky. Jinak se vypíše chybové hlášení, což může být způsobeno buď chybou v programu anebo tím, že program byl moc náročný a vyčerpal přidělený čas, takže byl „shozen“.

Příklad: Pražané bez článku na české Wikipedii editovat

V prvním příkladu vypíšeme seznam lidí, kteří se narodili v Praze a nemají článek na české Wikipedii. Dotaz má dvě hlavní části, SELECT (anglicky „vyber“), kam se napíše, které položky chceme vypsat, a WHERE (anglicky „kde“), kam do složených závorek zapíšeme podmínky výběru dat. Za jednotlivými částmi programu jsou komentáře uvozené znakem #. Ty neovlivňují průběh výpočtu, jenom přispívají snadnému pochopení programu.

SELECT ?item ?itemLabel # seznam položek, které mají být ve výpisu
WHERE
  {
    ?item wdt:P19 wd:Q1085 # kdokoli - místo narození (P19) - Praha (Q1085)
      FILTER NOT EXISTS { ?w schema:about ?item FILTER regex(STR(?w) , "https://cs.wikipedia")}    .
        # filtr: hledaná položka nemá záznam na české Wikipedii
    SERVICE wikibase:label {bd:serviceParam wikibase:language "cs,sk,en,de,fr,pl" .} 
        # služba, která poskytuje popisky (...Label) a požadované jazyky popisků v pořadí preference
  }

Důležitou součástí programu jsou proměnné, které poznáme podle otazníku před jménem. Jsou to jakési žolíky, které mohou zastupovat jakoukoli informaci vyhovující daným podmínkám. Pomocí proměnné ?item, zastupující hledané položky, konstruujeme základní prvek podmínky WHERE, řádek

?item wdt:P19 wd:Q1085

Ten říká, že dotyčný (?item) má vlastnost „místo narození“ (P19), a ta nabývá hodnotu „Praha“ (wd:Q1085). Pokud bychom chtěli dotaz modifikovat, například pro výpis lidí zesnulých v Brně, museli bychom napřed zjistit kódy požadovaných vlastností a hodnot v databázi Wikidata. Označení vlastností a položek se nejsnáze zjišťuje tak, že si na Wikidatech (https://www.wikidata.org/wiki/Wikidata:Main_Page) vyhledáme podobnou položku (například nějakého člověka zemřelého v Brně, kterého známe, třeba Elišku Rejčku), a při pohybu myši nad patřičnou položkou se ukáže její označení. Tím zjistíme, že uvedený řádek je potřeba nahradit tímto:

?item wdt:P20 wd:Q14960

protože P20 znamená místo úmrtí a Q14960 je kód Brna. Zkuste si to a vytvoříte seznam lidí, kteří zemřeli v Brně a nemají článek na české Wikipedii.

Dalšími prvky dotazu bývají různé filtry (logické podmínky, které musejí záznamy plnit), prefixy zastupující jednotlivé zdroje informací (třeba wd:) či funkce jako STR(), která převádí svůj argument na textový řetězec). V našem dotazu najdeme také regulární výraz regex(), který zjišťuje, zda daný odkaz vede na českou Wikipedii, a volání služby (SERVICE) wikibase:label, která k číselným kódům umí doplnit jejich slovní popis. Tyto detaily nejsou pro práci s dotazem tak důležité, stačí je prostě ponechat na místě beze změny.

Zobecnění tohoto příkladu pro narození v libovolném místě ČR je uvedeno na konci kapitoly Příklad: Biologické druhy.

Příklad: Velehory editovat

Následující dotaz vyhledá hory, které nemají svůj článek na české Wikipedii a měří víc než 4000 metrů. Vypíše se odkaz na Wikidata, popisek (název), výška hory a počet projektů Wikimedia, v nichž se hora objevuje. Výpis je seřazen (ORDR BY) sestupně (DESC) podle počtu projektů a je uvedeno jen 30 prvních hor.

Řazení se provádí proto, že položky přítomné na velkém počtu projektů jsou obvykle zajímavější, důležitější a na Wikipedii lépe podchycené než ty, které se vyskytují jen zřídka. Samozřejmě tomu tak není vždy a je potřeba si dávat pozor na případy, kdy je nějaký článek uměle prosazen na různé projekty v rámci „marketingové kampaně“ někoho, kdo investuje do překladů do cizích jazyků.

SELECT ?item ?itemLabel ?vyska (COUNT(distinct ?sitelink) as ?pocet_projektu) # funkce COUNT spočte projekty 
WHERE
{
    ?item wdt:P31 wd:Q8502    # položka (item) je typu hora (Q8502)
      FILTER NOT EXISTS { ?wcs schema:about ?item FILTER regex(STR(?wcs) , "https://cs.wikipedia")} .    
      # filtr: hledaná položka nemá záznam na české Wikipedii
    ?item wdt:P2044 ?vyska	FILTER (?vyska > 4000) .  # má vlastnost výška (P2044) a odfiltruji jen ty hory, kde je výška > 4000 
    ?sitelink schema:about ?item FILTER regex(STR(?sitelink), "wikipedia") .  # seznam odkazů, zajímají mě jen odkazy na Wikipedie
    SERVICE wikibase:label {bd:serviceParam wikibase:language "cs,sk,en,de,fr,pl" .} 
        # chci popis česky, a když není, tak slovensky, anglicky, německy atd.
}
GROUP BY ?item ?itemLabel ?vyska # vlastně seznam pevných polí z výpisu; chybí zde počet projektů, který se dopočítá
ORDER BY DESC(?pocet_projektu)  # seřadím sestupně podle počtu projektů, v nichž se položka vyskytuje
LIMIT 30 # vypíši jen 30 položek

Jak víme, v jazyce SPARQL se při výběru (v části WHERE) pracuje s trojicemi tvaru položka – označení vlastnosti – hodnota vlastnosti. Tyto trojice se propojují tečkami. První trojice v našem příkladu je

      ?item wdt:P31 wd:Q8502

a znamená: položka ?item má vlastnost P31 (v nomenklatuře Wikidat je to „instance of“, tedy „případ čeho“) a tyto vlastnost nabývá hodnoty Q8502 („mountain“ čili „hora“). Tato trojice je doplněna již známým filtrem zaručujícím, že se budou vypisovat jen položky bez článku na české Wikipedii. Za ní po oddělující tečce následuje další trojice:

      ?item wdt:P2044 ?vyska

K ní je připojen filtr, který nám „odmaže“ příliš malé hory – rozhodli jsme se, že chceme překládat články jen o těch opravdu vysokých.

A konečně poslední trojice

      ?sitelink schema:about ?item

vypisuje všechny odkazy do projektů Wikimedia, které se vztahují k hledané položce ?item. Následující filtr ponechává pouze odkazy na Wikipedie. Tato poslední trojice je jen pomůcka, která slouží jako předpoklad spočítání odkazů do jiných projektů, abychom podle tohoto počtu mohli výstup seřadit.

Wikidata umožňují zobrazit výsledky na mapě, pokud do výstupu doplníme souřadnice (vlastnost P625). Před dotaz navíc musíme vložit komentář

 #defaultView:Map

aby server věděl, že chceme mapový výstup.

#defaultView:Map
SELECT ?item ?itemLabel ?vyska ?coord (COUNT(distinct ?sitelink) as ?pocet_projektu) # funkce COUNT spočte projekty 
WHERE
{
    ?item wdt:P31 wd:Q8502    # položka (item) je typu hora (Q8502)
      FILTER NOT EXISTS { ?wcs schema:about ?item FILTER regex(STR(?wcs) , "https://cs.wikipedia")} .    
      # filtr: hledaná položka nemá záznam na české Wikipedii
    ?item wdt:P2044 ?vyska	FILTER (?vyska > 4000) .  # má vlastnost výška (P2044) a odfiltruji jen ty hory, kde je výška > 4000 
    ?sitelink schema:about ?item FILTER regex(STR(?sitelink), "wikipedia") .  # seznam odkazů, zajímají mě jen odkazy na Wikipedie
    OPTIONAL { ?item wdt:P625 ?coord . } # souřadnice, je-li známá
    SERVICE wikibase:label {bd:serviceParam wikibase:language "cs,sk,en,de,fr,pl" .} 
        # chci popis česky, a když není, tak slovensky, anglicky, německy atd.
}
GROUP BY ?item ?itemLabel ?vyska ?coord # vlastně seznam pevných polí z výpisu; chybí zde počet projektů, který se dopočítá
ORDER BY DESC(?pocet_projektu)  # seřadím sestupně podle počtu projektů, v nichž se položka vyskytuje
LIMIT 30 # vypíši jen 30 položek

Kliknutím na bod na mapě zjistíme detaily o příslušném objektu.

Příklad: Spisovatelé, kteří mají článek na slovenské a ne na české Wikipedii editovat

Zde vypíšeme spisovatele, kteří mají článek na slovenské a ne na české Wikipedii.

SELECT ?item ?itemLabel  (COUNT(distinct ?sitelink) as ?count)
WHERE
{
   ?item wdt:P106 wd:Q36180 # povolání = spisovatel
      FILTER (NOT EXISTS { ?w schema:about ?item FILTER regex(STR(?w) , "https://cs.wikipedia")} 
               && EXISTS { ?w schema:about ?item FILTER regex(STR(?w) , "https://sk.wikipedia")}  ) .    
      # filtr: hledaná položka nemá záznam na české Wikipedii, ale má ho na slovenské
   ?sitelink schema:about ?item  FILTER regex(STR(?sitelink), "wikipedia") .
   SERVICE wikibase:label {bd:serviceParam wikibase:language "cs,sk,en,de,fr,pl" .}
}
GROUP BY ?item ?itemLabel 
ORDER BY DESC(?count)
LIMIT 30 # maximální počet položek ve výpisu

Schéma dotazu je podobné, za slovem WHERE vybíráme požadované vlastnosti a jejich hodnoty. Oproti minulému dotazu přibyla ve filtr položka EXISTS, který vybere jen spisovatele s článkem na slovenské Wikipedii, což je důležité, pokud chceme překládat ze slovenštiny. Je spojena s předchozí filtrační podmínkou pomocí &&, což znamená „a zároveň“.

Pokud chcete překládat z jiného jazyka než slovenštiny, je potřeba jeho zkratkou nahradit „sk“ v řádku && EXISTS. Například pokud byste chtěli překládat z polštiny, bude zde

               && EXISTS { ?w schema:about ?item FILTER regex(STR(?w) , "https://pl.wikipedia")}  ) .

Obecně platí, že když potřebujeme ve filtru spojit více logických podmínek, použijeme logické operátory && (a zároveň) nebo || (nebo), případně jednotlivé části uzávorkujeme kulatými závorkami (), abychom stroji sdělili, v jakém pořadí se mají operátory použít.

Například kdybychom chtěli vyhledávat všeobecně slavné lidi nebo i jen třeba slavné ženy, zjistíme, že server není schopný zvládnout tak velké množství záznamů ve vymezeném čase a dotaz nedobíhá. Nabízí se tedy vymezit vyhledávané osobnosti intervalem dat narození. Horní a dolní mez intervalu pak propojíme operátorem &&. například podmínka pro vyhledání žen narozených v posledních třech dekádách 19. století vypadá takto:

?item wdt:P31 wd:Q5 . # je to člověk
?item wdt:P21 wd:Q6581072 . # pohlaví = žena
?item wdt:P569 ?birth filter(year(?birth) > 1870 && year(?birth) < 1901 ) . # filtr na narození

Čím více se blížíme k 21. století, tím je potřeba intervaly dělat užší, protože je ve Wikipediích více záznamů.

Příklad: Biologické druhy editovat

Tento příklad ukazuje postupné zlepšování (a zároveň zesložiťování) dotazu na výběr biologických druhů. Nepočítáme zde projekty, ve kterých se článek o druhu vyskytuje, protože by to ukázku zkomplikovalo a zpomalilo dotazy, takže by nemusely doběhnout. Pokud byste to někdy potřebovali, pomůžete si podle vzoru následujícího příkladu vloženým dotazem.

Nejdřív vyrobíme seznam špačkovitých ptáků (čeleď Sturnidae) na Wikidatech a podíváme se, kteří již mají článek na české Wikipedii. Vypíšeme odkaz na Wikidata, jméno ptáka, jeho biologický rod a případně odkaz na českou Wikipedii, pokud existuje. Výstup seřadíme podle rodu a jména ptáka.

SELECT DISTINCT ?item ?itemLabel ?rodLabel ?wcs
WHERE
{
    ?item wdt:P105 wd:Q7432 . # taxon hledaného objektu = druh Q7432 
    ?item wdt:P171 ?rod . # rodičovský taxon hledaného objektu je libovolný rod
    ?rod wdt:P171 wd:Q185237 . # rodičovský taxon rodu = Sturnidae (špačkovití), Q185237
    OPTIONAL { ?wcs schema:about ?item . ?wcs schema:inLanguage "cs" } # pokud je v CS Wikipedii, tak link
    SERVICE wikibase:label {bd:serviceParam wikibase:language "cs,en,de,fr,sk,pl" .}
}
ORDER BY ?rodLabel ?itemLabel

První tři řádky v podmínce WHERE říkají, že chceme vypsat položky (?item), která jsou na taxonomické úrovni druh a patří do libovolného rodu, ale rodičovský taxon jejich rodu je Sturnidae (špačkovití), tedy položka Q185237 v databázi Wikidata. Proměnná ?rod je použita jako zprostředkovatel mezi druhem a čeledí, protože položka druhu neobsahuje přímý odkaz na čeleď.

Protože odkaz na českou Wikipedii není u všech ptáků, jen u těch, o kterých tam existuje článek, musíme použít klauzuli OPTIONAL, aby se vypsali i špačkovití bez české verze. Ti budou mít v příslušném sloupci prázdnou buňku.

Metoda popsaná na špačkovitých nefunguje u čeledi turovití (Bovidae, Q25497) která obsahuje několik podčeledí. Položky v databázi Wikidata jsou napojeny na čeleď buď přes rod, anebo častěji přes rod a podčeleď. V dotazu tedy musíme pomocí slova UNION spojit obě možné cesty. Jinak je dotaz konstruován stejně jako předchozí špaččí.

SELECT DISTINCT ?item ?itemLabel ?rodLabel ?wcs
WHERE
{
    {
      ?item wdt:P105 wd:Q7432 . # taxon hledaného objektu = druh Q7432 
      ?item wdt:P171 ?rod . # rodičovský taxon hledaného objektu je libovolný rod
      ?rod wdt:P171 wd:Q25497 . # rodičovský taxon rodu 
    } # vazba druh - rod - čeleď 
  UNION
    {
      ?item wdt:P105 wd:Q7432 . # taxon hledaného objektu = druh Q7432 
      ?item wdt:P171 ?rod . # rodičovský taxon hledaného objektu je libovolný rod
      ?rod wdt:P171 ?podceled . # rodičovský taxon rodu je libovolná podčeleď
      ?podceled wdt:P171 wd:Q25497 . # rodičovský taxon podčeleďi  
    } # vazba druh - rod - podčeleď - čeleď 
    OPTIONAL { ?wcs schema:about ?item . ?wcs schema:inLanguage "cs" } 
    SERVICE wikibase:label {bd:serviceParam wikibase:language "cs,en,de,fr,sk,pl" .}
}
ORDER BY ?rodLabel

Pro případ ještě složitějších vazeb mezi taxony, kde vystupují (nebo také nevystupují) podčeledi a nadčeledi a tak podobně je ovšem tento způsob také nedostatečný. V tom případě je vhodné použít konstrukci s hvězdičkou *, která znamená, že se v databázi hledají libovolně hluboko zanořené podtaxony. Příklad s turovitými pak vypadá takto:

SELECT DISTINCT ?item ?itemLabel ?rodLabel ?wcs
WHERE
{
    ?item wdt:P105 wd:Q7432 . # taxon hledaného objektu = druh Q7432 
    ?item wdt:P171* ?rod . # nadtaxon hledaného objektu je libovolný rod
    ?rod wdt:P105 wd:Q34740 . # taxon rodu = rod Q34740
    ?item wdt:P171* wd:Q25497 . # nadtaxon hledaného objektu je Turovití Q25497 
   
    OPTIONAL { ?wcs schema:about ?item . ?wcs schema:inLanguage "cs" } 
    SERVICE wikibase:label {bd:serviceParam wikibase:language "cs,en,de,fr,sk,pl" .}
}
ORDER BY ?rodLabel

Tento dotaz se také lépe zobecňuje, stačí místo Q25497 napsat jakýkoli jiný rod či vyšší taxonomickou jednotku a databáze vyhledá její členy.

Podobně můžeme zobecnit výše uvedený příklad na vyhledávání rodáků z Prahy, kteří nejsou na české Wikipedii. Pokud nás nezajímá jen Praha, ale libovolná obec v Česku, můžeme napsat:

SELECT ?item ?itemLabel ?mestoLabel (COUNT(distinct ?sitelink) as ?pocet_projektu)
WHERE
  {
    ?item wdt:P19 ?mesto .
     ?mesto  wdt:P31* wd:Q5153359  
      FILTER NOT EXISTS { ?w schema:about ?item FILTER regex(STR(?w) , "https://cs.wikipedia")}    .
      ?sitelink schema:about ?item FILTER regex(STR(?sitelink), "wikipedia") .  # seznam odkazů, zajímají mě jen odkazy na Wikipedie
    SERVICE wikibase:label {bd:serviceParam wikibase:language "cs,sk,en,de,fr,pl" .} 
  }
GROUP BY ?item ?itemLabel ?mestoLabel
ORDER BY DESC(?pocet_projektu)
LIMIT 100

To využívá třídu Q5153359, administrativní jednotka v ČR, a ptá se na narození v čemkoli, co patří do nějaké administrativní jednotky v ČR, třeba i přes víc stupňů vnoření.

Příklad: Vyznamenaní editovat

Tento dotaz vybere lidi vyznamenané velkým křížem německého řádu Za zásluhy, kteří nemají článek na české Wikipedii, a přidá několik užitečných informací z Wikidat. (Vlastnost „vyznamenání“ je v kódovníku Wikidat zaznamenávána jako P166 a velký kříž tohoto řádu má kód Q10905235.)

Dotaz vypisuje mimo jiné i data narození a úmrtí. Datum uložené v původním formátu je špatně čitelné lidskýma očima, proto je v úvodní části dotazu za příkazem SELECT potřeba pomocí funkcí DAY (den), MONTH (měsíc) a YEAR (rok) z něj vybrat příslušné části, pomocí funkce STR je převést z číslovky na řetězec znaků a pomocí funkce CONCAT složit dohromady a doplnit tečkami.

Další zajímavostí jsou vložené klauzule OPTIONAL, které se používají v případě, kdy se může stát, že hledaná informace pro některé položky chybí.

Dotaz obsahuje dva poddotazy SELECT, které se používají pro vytažení údajů o povolání a o počtu projektů Wikimedia, na kterých se osoba nalézá. Nevýhodou je, že do obou je potřeba přepsat ještě jednou podmínku pro vyhledání, v našem případě

 ?item wdt:P166 wd:Q10905235.

To není příliš pohodlné (a je obecně známkou špatného programátorského stylu, když se stejná věc musí v programu objevit vícekrát zopakovaná). Zde to však nejspíš nelze snadno obejít.

Do programu je na konci zařazen filtr, který smaže vyznamenané, kteří se objevují na méně než 5 projektech. Zakomentováním nebo smazáním tohoto řádku získáme úplný výpis.

SELECT ?item ?itemLabel 
(CONCAT(STR(DAY(?datumnar)), ". ", STR(MONTH(?datumnar)), ". ", STR(YEAR(?datumnar))) as ?d1) ?mistonarLabel 
(CONCAT(STR(DAY(?datumumr)), ". ", STR(MONTH(?datumumr)), ". ", STR(YEAR(?datumumr))) as ?d2) ?mistoumrLabel 
 ?misLabel  ?masLabel ?pocet_projektu

WHERE
{
    ?item wdt:P166 wd:Q10905235 . # nositel velkokříže německého Řádu za zásluhy 
    OPTIONAL {?item wdt:P569 ?datumnar}
    OPTIONAL {?item wdt:P19 ?mistonar}
    OPTIONAL {?item wdt:P570 ?datumumr}
    OPTIONAL {?item wdt:P20 ?mistoumr}
    OPTIONAL { # tohle vybere dvě z povolání toho člověka 
       SELECT ?item (MIN(?x) as ?mis) (MAX(?x) as ?mas) # zneužívá funkce MIN a MAX pro výběr vzorku povolání
       WHERE{ ?item wdt:P166 wd:Q10905235 . # ještě jednou vyhledávací podmínka
             ?item wdt:P106 ?x . 
            FILTER NOT EXISTS { ?wcs schema:about ?item . ?wcs schema:inLanguage "cs" }
            SERVICE wikibase:label {bd:serviceParam wikibase:language "cs,en,de,sk,fr,pl" .}
            } 
       GROUP BY ?item      
    } 
    { # tohle spočítá, na kolika projektech má článek
       SELECT ?item (COUNT(distinct ?sitelink) as ?pocet_projektu)
       WHERE{ ?item wdt:P166 wd:Q10905235 .  # do třetice stejná vyhledávací podmínka
             ?sitelink schema:about ?item FILTER regex(STR(?sitelink), "wikipedia").
            FILTER NOT EXISTS { ?wcs schema:about ?item . ?wcs schema:inLanguage "cs" }
            SERVICE wikibase:label {bd:serviceParam wikibase:language "cs,en,de,sk,fr,pl" .}
            } 
       GROUP BY ?item      
    }
    FILTER ( ?pocet_projektu > 4 ) # minimální počet projektů, které mají danou osobu uvádět
    FILTER NOT EXISTS { ?wcs schema:about ?item . ?wcs schema:inLanguage "cs" } # není česky
    SERVICE wikibase:label {bd:serviceParam wikibase:language "cs,en,de,sk,fr,pl" .}        
}
ORDER BY DESC(?pocet_projektu)  # seřadím sestupně podle počtu projektů, v nichž se položka vyskytuje

LIMIT 1000 # maximální počet položek ve výpisu

Pozor, ve výpisu se jedna osoba může objevit vícekrát, pokud má například uvedeno více dat narození. Šlo by to odfiltrovat, ale zde je to spíše užitečné, protože je hned vidět nejednoznačnost v údajích.