Query » History » Version 6

Jakub Jirůtka, 08/23/2011 08:08 PM
přidán stručný popis implementace

1 1 Jakub Jirůtka
h1. Vyhledávání
2 1 Jakub Jirůtka
3 2 Jakub Jirůtka
{{>toc}}
4 1 Jakub Jirůtka
5 2 Jakub Jirůtka
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á.
6 1 Jakub Jirůtka
7 1 Jakub Jirůtka
8 2 Jakub Jirůtka
h2. Předdefinované dotazy
9 1 Jakub Jirůtka
10 2 Jakub Jirůtka
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.
11 1 Jakub Jirůtka
12 2 Jakub Jirůtka
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.
13 1 Jakub Jirůtka
14 2 Jakub Jirůtka
15 1 Jakub Jirůtka
h2. Dotazovací jazyky pro webové služby
16 1 Jakub Jirůtka
17 1 Jakub Jirůtka
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é.
18 1 Jakub Jirůtka
19 1 Jakub Jirůtka
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).
20 1 Jakub Jirůtka
21 1 Jakub Jirůtka
22 1 Jakub Jirůtka
h2. RSQL
23 1 Jakub Jirůtka
24 5 Jakub Jirůtka
*UPOZORNĚNÍ: Integrace RSQL ještě není úplně dokončená, takže pro některé zdroje a konkrétní atributy nemusí fungovat správně!*
25 1 Jakub Jirůtka
26 2 Jakub Jirůtka
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.
27 1 Jakub Jirůtka
28 2 Jakub Jirůtka
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.
29 1 Jakub Jirůtka
30 2 Jakub Jirůtka
31 1 Jakub Jirůtka
h3. Struktura výrazu
32 1 Jakub Jirůtka
33 5 Jakub Jirůtka
Výraz se skládá z jednoho či více _kritérií_, které se spojují logickými (Booleovskými) operátory.
34 1 Jakub Jirůtka
35 1 Jakub Jirůtka
* _výraz_ = [ "(" ] ( _podmínka_ / _výraz_ ) [ _logický-operátor_ ( _podmínka_ / _výraz_ ) ] [ ")" ]
36 1 Jakub Jirůtka
* _podmínka_ = _selektor_ _operátor-porovnání_ _argument_
37 4 Jakub Jirůtka
* _logický-operátor_ = @";" / "&" / " and " / "," / "|" / " or "@
38 4 Jakub Jirůtka
* _operátor-porovnání_ = @"==" / "=" / "!=" / "=lt=" / "<" / "=le=" / "<=" / "=gt=" / ">" / "=ge=" / ">="@
39 5 Jakub Jirůtka
* _selektor_ = @["a"-"z","A"-"Z","_","0"-"9","-"] ("." ["a"-"z","A"-"Z","_","0"-"9","-"] )*@
40 4 Jakub Jirůtka
* _argument_ = @~["(",")",";",","," "]+ / "'" ~["'"]+ "'" / "\"" ~["\""]+ "\""@
41 1 Jakub Jirůtka
42 1 Jakub Jirůtka
43 1 Jakub Jirůtka
h3. Logické operátory
44 1 Jakub Jirůtka
45 3 Jakub Jirůtka
|_. Název	|_. FIQL		|_. Alternativní	|
46 3 Jakub Jirůtka
| AND		| @;@		| "@ and @"		|
47 3 Jakub Jirůtka
| OR		| @,@		| "@ or @"		|
48 1 Jakub Jirůtka
49 1 Jakub Jirůtka
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ů.
50 1 Jakub Jirůtka
51 1 Jakub Jirůtka
52 1 Jakub Jirůtka
h3. Operátory porovnání
53 1 Jakub Jirůtka
54 1 Jakub Jirůtka
|_. Název			|_. FIQL		|_. Alternativní		|_. Platné datové typy							|
55 1 Jakub Jirůtka
| rovná se			| @==@		| @=@				| textový řetězec, číslo, datum, výčtový typ, XLink	|
56 1 Jakub Jirůtka
| nerovná se		        | @!=@		| @!=@				| textový řetězec, číslo, datum, výčtový typ, XLink	|
57 1 Jakub Jirůtka
| menší než			| @=lt=@	| @<@				| číslo, datum									|
58 1 Jakub Jirůtka
| menší nebo rovno	| @=le=@	| @<=@				| číslo, datum									|	
59 1 Jakub Jirůtka
| větší než			| @=gt=@	| @>@				| číslo, datum									|
60 1 Jakub Jirůtka
| větší nebo rovno	| @=ge=@	| @>=@				| číslo, datum									|
61 1 Jakub Jirůtka
62 5 Jakub Jirůtka
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 (neplatí pro [[Query#„Dereference“-vazeb-aka-JOIN|dereferencované]] atributy). V opačném případě vyhledává pouze ve zvoleném jazyce (podle Accept-Language, nebo  [[URLParameters#lang|lang]]).
63 1 Jakub Jirůtka
64 4 Jakub Jirůtka
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_am*@ vyhoví všechny předměty, jejichž název začíná na „prog“, následuje jeden libovolný znak, pak „am“ a cokoli (opět bez ohledu na velikost písmen).
65 1 Jakub Jirůtka
66 1 Jakub Jirůtka
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.
67 1 Jakub Jirůtka
68 1 Jakub Jirůtka
Pakliže argument obsahuje mezery, kulaté závorky, čárku nebo dvojtečku, tak musí být uzavřen v uvozovkách (jednoduchých nebo dvojitých). V opačném případě jsou uvozovky nepovinné.
69 1 Jakub Jirůtka
70 5 Jakub Jirůtka
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.
71 1 Jakub Jirůtka
72 1 Jakub Jirůtka
73 5 Jakub Jirůtka
h3. „Dereference“ vazeb (aka JOIN)
74 5 Jakub Jirůtka
75 5 Jakub Jirůtka
V dotazu je možné přistupovat i k atributům _odkazovaných_ zdrojů (na které vede XLink) pomocí tzv. „dereference“. Jinak řečeno umožňuje zápis podmínky s _implicitním_ spojením (_JOINem_) entit, mezi kterými existuje explicitní průchozí vazba (obdobně jako v HQL(Hibernate Query Language)). Vazbami se prochází pomocí tečkové notace a je možné i zanořování. Kupříkladu @unit.unitType==FACULTY@ vybere všechny záznamy, které jsou ve vztahu s organizační jednotkou _typu_ fakulta. Na pozadí dojde k vygenerování polospojení (_LEFT JOIN_) tabulky předmětů s tabulkou nákladových středisek a podmínky unitType=FACULTY.
76 5 Jakub Jirůtka
77 5 Jakub Jirůtka
Mějte prosím na paměti, že tyto dotazy mohou generovat velkou zátěž databáze. Jakmile bude KOSapi napojené přímo na KOS, bude tento problém dost citlivý. Používejte je proto obezřetně a vyhýbejte se zbytečně neefektivním dotazům. Z těchto důvodů jsem také omezil maximální počet implicitních _JOINů_ pro dotaz na 3.
78 5 Jakub Jirůtka
79 5 Jakub Jirůtka
80 1 Jakub Jirůtka
h3. Parametry
81 1 Jakub Jirůtka
82 1 Jakub Jirůtka
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]].
83 1 Jakub Jirůtka
84 1 Jakub Jirůtka
85 1 Jakub Jirůtka
h3. Příklady
86 1 Jakub Jirůtka
87 1 Jakub Jirůtka
* "<code>/courses?query=name==*prog*</code>":https://kosapi.fit.cvut.cz/api/3/courses?query=name=%2Aprog%2A - vrátí předměty, jejichž název obsahuje „prog“
88 4 Jakub Jirůtka
* "<code>/courses?query=name=='programování v*'</code>":https://kosapi.fit.cvut.cz/api/3/courses?query=name==%27programov%C3%A1n%C3%AD%20v*%27 - vrátí předměty, jejichž název začíná na „programování v“
89 4 Jakub Jirůtka
* "<code>/courses?query=credits>5</code>":https://kosapi.fit.cvut.cz/api/3/courses?query=credits%3E5 - vrátí předměty za více než 5 kreditů
90 4 Jakub Jirůtka
* "<code>/courses?query=season==WINTER;(completion==CLFD_CREDIT,completion==CREDIT)</code>":https://kosapi.fit.cvut.cz/api/3/courses?query=season==WINTER;%28completion==CLFD_CREDIT,completion==CREDIT%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
91 5 Jakub Jirůtka
* "<code>/courses?query=department.unitType==FACULTY</code>":https://kosapi.fit.cvut.cz/api/3/courses?query=department.unitType==FACULTY - vrátí předměty, které zajišťuje přímo libovolná fakulta (tzn. organizační jednotka typu fakulta)
92 4 Jakub Jirůtka
* "/teachers?query=extern==true&orderBy=lastName&maxResults=50":https://kosapi.fit.cvut.cz/api/3/teachers?query=extern==true&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ů
93 1 Jakub Jirůtka
94 6 Jakub Jirůtka
95 1 Jakub Jirůtka
h3. Pár slov k implementaci
96 1 Jakub Jirůtka
97 6 Jakub Jirůtka
RSQL(RESTful Resource Query Language) jsem vyvinul speciálně pro KOSapi, ale jeho návrh a implementace je dostatečně obecná i pro použití v jiných RESTových službách postavených nad relační databází. V dohledné době plánuji uvolnění zdrojových kódů pod open-source licencí.
98 6 Jakub Jirůtka
99 6 Jakub Jirůtka
Skládá se ze dvou navazujících knihoven. První je _RSQL-parser_, který provádí lexikální analýzu, parsování a sestavení objektové reprezentace zadaného RSQL(RESTful Resource Query Language) výrazu. Součástí je lexikální specifikace a EBNF(Extended Backus–Naur Form) gramatika zapsaná v "JavaCC":http://javacc.java.net/, ze které je vygenerován vlastní parser.
100 6 Jakub Jirůtka
101 6 Jakub Jirůtka
Druhou knihovnou je _RSQL-hibernate_. Ta zajišťuje převod dotazu na "Hibernate Criteria Query":http://docs.jboss.org/hibernate/core/3.5/reference/en/html/querycriteria.html (objektová reprezentace HQL(Hibernate Query Language), resp. SQL(Structured Query Language) dotazu), z něhož se následně generuje SQL(Structured Query Language) dotaz do relační databáze. V tomto procesu hrají hlavní roli _RSQLCriteriaBuilder_, sada _CriterionBuilders_ a _Mapper_. _CriteriaBuilder_ prochází strom výrazu, generuje _Criterion_ pro logické výrazy (AND, OR) a deleguje _kritéria_ (porovnání) na odpovídající _CriterionBuilder_. Ty má připravené v kolekci, jíž iteruje dokud nenalezne takový, který umí obsloužit daný selektor a operátor. Kromě obecného _CriterionBuilder_ obsahuje například takový, který umí vytvořit _Criterion_ pro atribut vazby (i s NaturalID), multijazyčný text, selektor s implicitním JOINem, příp. speciální pro nestandardní entity. _Mapper_ zajišťuje mapování _selektorů_ (názvů v XML, příp. cest) na názvy příslušných _atributů_ v entitách. Většina odpovídá 1:1, ale v některých případech je nutné použít přemapování (např. multijazyčné texty).
102 2 Jakub Jirůtka
103 2 Jakub Jirůtka
__
104 2 Jakub Jirůtka
^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.