W projekcie SYNAT intensywnie stosujemy technologie semantic web (po polsku czasem semantyczny Internet). Wykorzystujemy repozytorium RDF (OWLIM) do składowania dużych ilości danych. Do odpytywania repozytorium stosujemy języki SPARQL i SeRQL. Pierwszy z nich jest uznanym standardem, drugi (stworzony przez firmę Aduda, producenta repozytorium Sesame) według części z nas jest o wiele wygodniejszy w użyciu.
W ubiegłym postanowiliśmy, że niezależnie od tego, jako często stosujemy SPARQL, należałoby w końcu zrozumieć różnicę pomiędzy klauzulami FROM i FROM NAMED. Okazało się, że dotarcie do wiarygodnego i zrozumiałego źródła wcale nie jest takie proste, dlatego zamieszczamy ten wpis (oparty o wpis na prywatnym blogu osoby z zespołu).
Wydaje się, że największy problem brzmi w samej nazwie. Zarówno FROM jak i FROM NAMED operuja na grafach nazwanych, co z pewnością ma związek z zamieszaniem wokół tych słów kluczowych. Poniżej znajduje się krótka sekcja pytań i odpowiedzi, która powinna wyjaśnić sytuację.
Jeśli zapytanie nie zawiera FROM ani FROM NAMED, co właściwie jest odpytywane?
Odpytywany jest graf aktywny. Wbrew niektórym sugestiom, nie musi on mieć nic wspólnego z grafem domyślnym (ang. default graph). Przykładowo w OWLIM graf aktywny obejmuje całą zawartość repozytorium.
Przykład (ze specyfikacji SPARQL):
PREFIX foaf: <http://xmlns.com/foaf/0.1/> SELECT ?nameX ?nameY ?nickY WHERE { ?x foaf:knows ?y ; foaf:name ?nameX . ?y foaf:name ?nameY . OPTIONAL { ?y foaf:nick ?nickY } }
Co to jest graf aktywny?
Jest to graf (lub zbiór grafów) odpytywany, gdy nie zostały podane klauzule FROM i FROM NAMED. Może to być graf domyślny, może to być cała zawartość repozytorium… albo coś zupełnie innego, w zależności od implementacji.
Co to jest graf domyślny?
Graf domyślny to graf bez nazwy, lub inaczej – bez kontekstu. Jest to graf zbudowany z trójek RDF, a nie z czwórek.
Jak efekt ma klauzula FROM?
Klauzule FROM ograniczają zbiór odpytywanych grafów. Szablon przedstawiony w zapytaniu zostanie dopasowany tylko do grafu (lub grafów) zdefiniowanego w klauzuli (klauzulach) FROM.
Przykład. Uwzględnione zostaną jedynie trójki z grafu <http://example.org/foaf/aliceFoaf>.
PREFIX foaf: <http://xmlns.com/foaf/0.1/glt; SELECT ?name FROM <http://example.org/foaf/aliceFoaf> WHERE { ?x foaf:name ?name }
Jaki efekt ma klauzula FROM NAMED?
Sprawia ona, że do każdej zmiennej reprezentującej w zapytaniu graf nazwany dopasowane zostaną tylko grafy podane w klazulach FROM NAMED.
Przykład (łączący FROM i FROM NAMED). Zmienna ?g zostanie dopasowana albo do grafu <http://example.org/alice>, albo do <http://example.org/bob>, ale nie do żadnego innego grafu nazwanego.
PREFIX foaf: <http://xmlns.com/foaf/0.1/> PREFIX dc: <http://purl.org/dc/elements/1.1/> SELECT ?who ?g ?mbox FROM <http://example.org/dft.ttl> FROM NAMED <http://example.org/alice> FROM NAMED <http://example.org/bob> WHERE { ?g dc:publisher ?who . GRAPH ?g { ?x foaf:mbox ?mbox } } <strong>Czy można łączyć FROM i FROM NAMED?</strong> Tak, jak widać powyżej. W przykładzie trójka nazwana musi należeć do jednego z grafów wymienionych w klauzuli FROM NAMED, a <span style="font-style: italic;">luźna</span> trójka zostanie dopasowana do trójki z grafu podanego w klauzuli FROM. <strong>A co, jeśli jest tylko jedna klauzula FROM NAMED?</strong> Wówczas poniższe dwa zapytania zwrócą dokładnie ten sam wynik: PREFIX foaf: <http://xmlns.com/foaf/0.1/> PREFIX dc: <http://purl.org/dc/elements/1.1/> SELECT ?who ?mbox FROM <http://example.org/dft.ttl> FROM NAMED <http://example.org/alice> WHERE { ?g dc:publisher ?who . GRAPH ?g { ?x foaf:mbox ?mbox } }
jest równoważne z:
PREFIX foaf: <http://xmlns.com/foaf/0.1/> PREFIX dc: <http://purl.org/dc/elements/1.1/> SELECT ?who ?mbox FROM <http://example.org/dft.ttl> WHERE { ?g dc:publisher ?who . GRAPH <http://example.org/alice> { ?x foaf:mbox ?mbox } }
Czy w SeRQL jest łatwiej?
Tak. Funkcjonalność odpowiadająca FROM i FROM NAMED jest realizowana przez klauzulę FROM CONTEXT. Przykład (ze specyfikacji SeRQL ):
SELECT name, mbox FROM CONTEXT <http://example.org/context/graph2> {x} foaf:name {name}; foaf:mbox {mbox} USING NAMESPACE foaf = <http://xmlns.com/foaf/0.1/>