h1. Vyhledávání {{>toc}} Komplexní podpora dotazování tvoří jednu ze základních funkcionalit databází. Oproti tomu většina běžných RESTových služeb nenabízí moc silné prostředky pro dotazování a omezuje se pouze na triviální předdefinované dotazy, příp. fulltextové vyhledávání. Ovšem mají-li webové služby IS(informačního systému) sloužit aplikacím jako přímý ^1^ zdroj dat, tak je komplexnější podpora vyhledávání prakticky nezbytná. h2. Předdefinované dotazy Všechny zdroje s parametrem v URI(Uniform Resource Identifier) jsou v podstatě předdefinované vyhledávací dotazy. Kupříkladu "/units/18000":https://kosapi.fit.cvut.cz/api/3/units/18000/ vyhledá _organizační jednotku_ s kódem _18000_. Na pozadí dojde k vygenerování _SELECTu_ nad tabulkou nákladových středisek, kde kód střediska je rovný 18000. To je poměrně triviální dotaz. Trochu složitější se skrývá například za "/programmes/MI/courses":https://kosapi.fit.cvut.cz/api/3/programmes/MI/courses, který vyhledá všechny _předměty_ patřící pod _studijní program_ s kódem _MI_. Zde se vygeneruje polospojení nad programy, spojovou tabulkou a předměty, kde program má kód rovný MI. Omezení takovýchto dotazů jsou zjevná. Co když potřebujeme například vyhledat všechny předměty, které se vyučují v zimním semestru, zajišťuje je Katedra softwarového inženýrství FIT a jejich název obsahuje slovo „prog“? Tady už potřebujeme nějaký dotazovací jazyk, který nám umožní kombinovat podmínky. h2. Dotazovací jazyky pro webové služby Existují dva standardy (alespoň co jsem našel), které definují jazyk pro dotazování nad RESTovými webovými službami. Prvním je obsáhlý "Open Data Protocol":http://www.odata.org, který mimo jiné zahrnuje komplexní podporu pro dotazování. Využití OData pro KOSapi jsem z několika důvodů zavrhl a vzhledem k tomu, že podpora vyhledávání je přímo jeho součástí, tak mi její _samostatné_ využití nepřišlo přínosné. Druhým je návrh IETF(Internet Engineering Task Force) standardu "Feed Item Query Language":http://tools.ietf.org/html/draft-nottingham-atompub-fiql-00, který definuje „URI-friendly“ syntaxi pro dotazování (správně spíš _vyhledávání_) nad Atom Feeds. Umožňuje vyhledávat záznamy Atom Entry podle jejich _metadat_. Jedná se pouze o návrh („draft“) z roku 2007, kterýžto nakonec nebyl standardizován, nicméně už jej implementuje např. framework "Apache CXF":http://cxf.apache.org. Syntaxe FIQL(Feed Item Query Language) je výhodná svým prvoplánovým určením pro zápis v URI(Uniform Resource Identifier), díky čemuž ji není potřeba zakódovávat. To ovšem můžeš být zároveň nevýhodou, neb kvůli tomu není příliš intuitivní. Jelikož jsem si stejně musel napsat vlastní parser, rozhodl jsem se tuto syntaxi využít a rozšířit ji ještě o alternativní zápis ala Java. Tím vznikl RESTful Resource Query Language (RSQL). h2. RSQL *UPOZORNĚNÍ: Integrace RSQL ještě není úplně dokončená, takže pro některé zdroje a konkrétní atributy nemusí fungovat správně! Ještě nefungují podmínky pro XLink vazby a možná dojde k drobným změnám v syntaxi (použití uvozovek).* RSQL(RESTful Resource Query Language) umožňuje vyhledávat záznamy (Atom Entry) podle jejich strukturovaných elementů (atributů) v Atom Content. Tím se také odlišuje od FIQL(Feed Item Query Language), který je naopak určený pouze pro vyhledávání záznamů podle jejich _metadat_ v Atom Entry. Všechny zdroje KOSapi jsou koncipované tak, že Atom elementy využívají pouze pro metadata a vlastní data z KOSu jsou obsažená v Atom Content ve strukturované podobě (závisí na _Content-Type_, výchozí je XML(Extensible Markup Language)). RSQL(RESTful Resource Query Language) dotazy se v KOSapi překládají na SQL(Structured Query Language) dotazy do KOSu. Jak již bylo napsáno, RSQL(RESTful Resource Query Language) umožňuje dva způsoby zápisu - „URI-friendly“ syntaxi FIQL(Feed Item Query Language) a alternativní syntaxi inspirovanou Javou. h3. Struktura výrazu Výraz se skládá z jednoho či více _porovnání_, které se spojují logickými (Booleovskými) operátory. * _výraz_ = [ "(" ] ( _podmínka_ / _výraz_ ) [ _logický-operátor_ ( _podmínka_ / _výraz_ ) ] [ ")" ] * _podmínka_ = _selektor_ _operátor-porovnání_ _argument_ * _logický-operátor_ = "@;@" / "@&@" / "@ and @" / "@,@" / "@|@" / "@ or @" * _operátor-porovnání_ = ( "@==@" / "@=@" / "@!=@" / "@=lt=@" / "@<@" / "@=le=@" / "@<=@" / "@=gt=@" / "@>@" / "@=ge=@" / "@>=@" ) * _selektor_ = @[a-zA-Z_]([a-zA-Z_0-9\-])*@ * _argument_ = ( "@'@" @[^']+@ "@'@" / "@"@" @[^"]+@ "@"@" ) h3. Logické operátory |_. Název |_. FIQL |_. Alternativní | | AND | @;@ | "@ and @" | | OR | @,@ | "@ or @" | Operátor AND má standardně přednost, tj. všechny operátory OR se vyhodnocují až po něm. Toto chování samozřejmě lze změnit pomocí uzávorkování výrazů. h3. Operátory porovnání |_. Název |_. FIQL |_. Alternativní |_. Platné datové typy | | rovná se | @==@ | @=@ | textový řetězec, číslo, datum, výčtový typ, XLink | | nerovná se | @!=@ | @!=@ | textový řetězec, číslo, datum, výčtový typ, XLink | | menší než | @=lt=@ | @<@ | číslo, datum | | menší nebo rovno | @=le=@ | @<=@ | číslo, datum | | větší než | @=gt=@ | @>@ | číslo, datum | | větší nebo rovno | @=ge=@ | @>=@ | číslo, datum | Porovnávání textových řetězců nezohledňuje velikost písmen (je _case insensitive_). Pokud je URL parametr [[URLParameters#multilang|multilang]] nastaven na @true@, tak zohledňuje texty v obou jazycích. V opačném případě vyhledává pouze ve zvoleném jazyce (podle Accept-Language, nebo [[URLParameters#lang|lang]]). Při porovnávání řetězců lze využít i _divoké karty_ a hledat pomocí nich i jen podle části řetězce. Způsob zápisu je stejný jako v SQL _LIKE_, pouze s tím rozdílem, že místo @%@ se zde používá @*@. Například podmínce @name='prog*'@ vyhoví všechny předměty, jejichž název začíná na „prog“ (opět bez ohledu na velikost písmen). V případě elementů, které reprezentují výčtový typ, je nutné jako argument uvádět _výčtový název_ (enum), nikoli jeho lokalizovaný popis. Argumentem pro XLink je identifikátor záznamu použitý v URI(Uniform Resource Identifier), což většinou bývá kód nebo ID. h3. Parametry RSQL(RESTful Resource Query Language) výraz se zapisuje do URL parametru [[URLParameters#query|query]] a je možné ho efektivně kombinovat s parametry [[URLParameters#startIndex|startIndex]], [[URLParameters#maxResults|maxResults]] a [[URLParameters#orderBy|orderBy]]. h3. Příklady * "/courses?query=name=='*prog*'":https://kosapi.fit.cvut.cz/api/3/courses?query=name=%27prog*%27 - vrátí předměty, jejichž název obsahuje „prog“ * "/courses?query=credits>'5'":https://kosapi.fit.cvut.cz/api/3/courses?query=credits%3E%275%27 - vrátí předměty za více než 5 kreditů * "/courses?query=season=='WINTER';(completion=='CLFD_CREDIT',completion=='CREDIT')":https://kosapi.fit.cvut.cz/api/3/courses?query=season==%27WINTER%27;%28completion==%27CLFD_CREDIT%27,completion==%27CREDIT%27%29 - vrátí předměty, které se vyučují v zimním semestru a jsou zakončené klasifikovaným zápočtem nebo zápočtem * "/teachers?query=extern=='true'&orderBy=lastName&maxResults=50":https://kosapi.fit.cvut.cz/api/3/teachers?query=extern==%27true%27&orderBy=lastName&maxResults=50 - vrátí vyučující externisty, seřadí je podle příjmení a výstup omezí na max. 50 záznamů h3. Pár slov k implementaci TODO __ ^1^ To znamená, že aplikace si nebudou uchovávat lokální kopii celé ani části databáze IS (cache se tím nevylučuje), ale budou je přímo získávat z webové služby.