rdf
linkeddata
SPARQL

SPARQLプロトコル


背景

世の中にはWeb上に散らばるデータを関連付けるためのLinked Dataという概念があります。リンク付されたデータを表すためのフォーマットにRDFがあります。RDFを検索するための言語としてSPARQLがあります。そしてSPARQLで問い合わせ可能なデータベースとしてSPARQL Endpointがあります。


SPARQLプロトコル

ここではSPARQLリクエストをSPARQL EndpoinにHTTPで送る方法を整理します。

SPARQLクエリの文法、レスポンスフォーマットの内容については扱いません。送信するSPARQLはSPARQL Endpointに登録されているラベルの数を取得する次のクエリとします。

SELECT (COUNT(?l) AS ?count)

WHERE {
?x <http://www.w3.org/2000/01/rdf-schema#label> ?l .
}

SPARQLクエリは、SQLクエリに似ています。


リクエスト

HTTPリクエストの送信方法はSPARQL 1.1 Protocol - 2.1 query operationで定義されています。

HTTPメソッドとしてGETまたはPOSTが選択できます。POSTメソッドではSPARQLクエリの指定方法が二つあります。

Endpointによってサポートしているリクエスト形式はまちまちです。例えば http://bio2rdf.org/sparql というURLのSPARQLエンドポイントはGETメソッドのみに対応しています。


GETメソッド

GETメソッドではHTTPリクエストのクエリパラメータでSPARQLクエリを指定します。パラメータ名はqueryです。

例えば、curlコマンドで、http://ep.lodqa.org/qald-biomed/queryというURLのEndpointにSPARQLクエリを投げるには次のようにしていします。

curl 'http://ep.lodqa.org/qald-biomed/query' -XGET -d query='SELECT (COUNT(?l) AS ?count) WHERE { ?x <http://www.w3.org/2000/01/rdf-schema#label> ?l . }'

この時、SPARQLクエリ文字列をURLエンコードする必要があります。上記のcurlコマンドの例ではcurlコマンドが-dオプションの引数を自動的にURLエンコードしてくれています。自分でURL文字列をつくる際には次のようにURLエンコードする必要があります。

http://ep.lodqa.org/qald-biomed/query?query=SELECT%20(COUNT(%3Fl)%20AS%20%3Fcount)%20WHERE%20%7B%20%3Fx%20%3Chttp%3A%2F%2Fwww.w3.org%2F2000%2F01%2Frdf-schema%23label%3E%20%3Fl%20.%20%7D

エンコードせずにSPARQLクエリを送信した場合、curlでは次のように400 Bad Requestレスポンスになります。

~ curl 'http://ep.lodqa.org/qald-biomed/query?query=SELECT (COUNT(?l) AS ?count) WHERE { ?x <http://www.w3.org/2000/01/rdf-schema#label> ?l . }' -v

* Trying 133.39.78.111...
* TCP_NODELAY set
* Connected to ep.lodqa.org (133.39.78.111) port 80 (#0)
> GET /qald-biomed/query?query=SELECT (COUNT(?l) AS ?count) WHERE ?x <http://www.w3.org/2000/01/rdf-schema HTTP/1.1
> Host: ep.lodqa.org
> User-Agent: curl/7.54.0
> Accept: */*
>
< HTTP/1.1 400 Bad Request
< Date: Thu, 01 Nov 2018 06:19:40 GMT
< Server: Apache
< Content-Length: 226
< Connection: close
< Content-Type: text/html; charset=iso-8859-1
<
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>400 Bad Request</title>
</head><body>
<h1>Bad Request</h1>
<p>Your browser sent a request that this server could not understand.<br />
</p>
</body></html>
* Closing connection 0

ブラウザでエンコードされていないURL http://ep.lodqa.org/qald-biomed/query?query=SELECT (COUNT(?l) AS ?count) WHERE { ?x <http://www.w3.org/2000/01/rdf-schema#label> ?l . } を開いた場合は、ブラザによって挙動が異なる可能性がありますが、Google ChromeやFirefoxでは次のメッセージを表示します。

{"message":"Encountered \" \"<\" \"< \"\" at line 1, column 41.\nWas expecting one of:\n    \"(\" ...\n    \"!\" ...\n    \"^\" ...\n    \"a\" ...\n    <Q_IRI_REF> ...\n    <PNAME_NS> ...\n    <PNAME_LN> ...\n    <VAR1> ...\n    <VAR2> ...\n    ","code":"MalformedQuery"}

大意としては、SPARQLクエリの形式が不正である意味のエラーメッセージです。


POSTメソッド

POSTメソッドではSPARQLクエリはHTTPリクエストのBODYに格納します。BODYの形式には2種類あります。


x-www-form-urlencoded

ブラウザのフォームからHTTPリクエストを送信する際の形式です。CURLコマンドの例です。

curl 'http://ep.lodqa.org/qald-biomed/query' -d query='SELECT (COUNT(?l) AS ?count) WHERE { ?x <http://www.w3.org/2000/01/rdf-schema#label> ?l . }'

-XGETをなくしただけで、あとは一緒です。curlコマンドは-dオプションを指定された場合のデフォルトのHTTPメソッドはPOSTです。またエンコード方式はapplication/x-www-form-urlencodedです。

前述したように、application/x-www-form-urlencodedはブラウザのフォームからHTTPリクエストを送信するときの形式です。次のようなHTMLフォームでSPARQLが実行できます。

<form action="http://ep.lodqa.org/qald-biomed/query">

<input name="query" value="SELECT (COUNT(?l) AS ?count) WHERE { ?x <http://www.w3.org/2000/01/rdf-schema#label> ?l . }">
<button>実行</button>
</form>

このときもSPARQLクエリを格納するパラメータ名はqueryです。


sparql-query

もうひとつのBODYの形式では、BODYに直接SPARQLクエリを書くことができます。curlの例です。

curl 'http://ep.lodqa.org/qald-biomed/query' -H 'Content-Type: application/sparql-query' -d 'SELECT (COUNT(?l) AS ?count) WHERE { ?x <http://www.w3.org/2000/01/rdf-schema#label> ?l . }'

この時BODYの形式を明示するためにHTTPヘッダにContent-Type: application/sparql-queryを指定する必要があります。またBODYの内容はSPARQL文字列だけす。query=は不要です。

おもにプログラムからSPARQLクエリを実行する際に使います。Rubyの例です。

Net::HTTP.post URI('http://ep.lodqa.org/qald-biomed/query'),

'SELECT (COUNT(?l) AS ?count) WHERE { ?x <http://www.w3.org/2000/01/rdf-schema#label> ?l . }',
'content-type' => 'application/sparql-query'

BODYにSPARQLクエリを文字列のまま指定できるので便利です。


レスポンスフォーマット

JSONとXMLを指定することができます。

例えば先程までのhttp://ep.lodqa.org/qald-biomed/queryへのリクエストでは、次のようなXML形式のレスポンスが帰ってきます。

<?xml version='1.0' encoding='UTF-8'?>

<sparql xmlns='http://www.w3.org/2005/sparql-results#'>
<head>
<variable name='count'/>
</head>
<results>
<result>
<binding name='count'>
<literal datatype='http://www.w3.org/2001/XMLSchema#integer'>30389</literal>
</binding>
</result>
</results>
</sparql>


JSON

JSONレスポンスフォーマットの指定方法はSPARQL 1.1 Query Results JSON Format - 6 Internet Media Type, File Extension and Macintosh File Type

で定義されています。

HTTPリクエストのHTTPヘッダにAccept: application/sparql-results+jsonを指定すると、レスポンスをJSON形式で取得できます。curlの例です。

curl 'http://ep.lodqa.org/qald-biomed/query' -H 'Content-Type: application/sparql-query' -H 'Accept: application/sparql-results+json' -d 'SELECT (COUNT(?l) AS ?count) WHERE { ?x <http://www.w3.org/2000/01/rdf-schema#label> ?l . }'

次のようにレスポンスはJSON形式になります。

{

"head" : {
"vars" : [
"count"
]
},
"results" : {
"bindings" : [
{
"count" : {
"datatype" : "http://www.w3.org/2001/XMLSchema#integer",
"type" : "literal",
"value" : "30389"
}
}
]
}
}

最近のプログラミング言語ではJSONのサポートが手厚いので、JSON形式が嬉しい場合があると思います。


XML

また明示的にXMLフォーマットを指定することもできます。

XMLレスポンスフォーマットの指定方法はSPARQL Query Results XML Format (Second Edition)

- 5. Internet Media Type, File Extension and Macintosh File Type

で定義されています。

HTTPリクエストのHTTPヘッダにAccept: application/sparql-results+xmlを指定すると、レスポンスをJSON形式で取得できます。curlの例です。

curl 'http://ep.lodqa.org/qald-biomed/query' -H 'Content-Type: application/sparql-query' -H 'Accept: application/sparql-results+xml' -d 'SELECT (COUNT(?l) AS ?count) WHERE { ?x <http://www.w3.org/2000/01/rdf-schema#label> ?l . }'

例えば http://bio2rdf.org/sparql というURLのSPARQLエンドポイントはのレスポンスのデフォルト形式はHTML形式です。この場合、明示的にXML形式を指定する必要があるかもしれません。


参考資料