2015年8月10日月曜日

TTLファイルのインポート

はじめに、ビルトーソにはTTLファイルのエクスポート機能は見当たりませんので、TTLファイルは独自にエクスポートしたものを使用しています。

TTLをインポートするには、画面からアップロードする方法と、コマンドからやる2通りの方法があります。

1つめの方法。
画面からインポートするには、コンダクターにログインして、Linked Data -> Quad Store Upload を選択します。そこからアップロードすることができます。こちらは画面を見ればわかると思います、簡単です。

2つめの方法。
コマンドからインポートするには、コマンドラインから、isqlと打ち込んでisql内で操作します。

TTLファイルを1つだけ取り込むにはこのコマンド。(SQL> はプロンプトです)
SQL> DB.DBA.TTLP_MT(file_to_string_output('ファイルの場所'),'','グラフ名');

例:
SQL> DB.DBA.TTLP_MT(file_to_string_output('/home/iastaff/ttl/public.ttl'),'','publicttl');


ディレクトリ内のすべてのTTLファイルを取り込む事もできるようです。
それは以下のサイト参照。
http://wiki.lifesciencedb.jp/mw/SPARQLthon19/TripleLoad#TTL.E3.81.AE.E3.83.AD.E3.83.BC.E3.83.89.28DB.DBA.TTLP_MT.29

しかし、複数のTTLファイルを取り込むのはいいけど、1つのグラフに入ってしまうようにも見えます。(試してません)


また、上記コマンドを実行した際に、以下のようにアクセス許可が無いよとエラーが出ることもあろうかと思います。(Allowかと思います。)

*** Error 42000: VD [Virtuoso Server]FA003: Access to '/home/hodade/ttl/public.ttl' is denied due to access control in ini file

そのときは、virtuoso.ini の DirsAllowedにアクセス許可するディレクトリをカンマ区切りで追加しましょう。

DirsAllowed              = ., ../vad, /home/hodade


その後、Virtuosoを再起動すると、この設定は反映されます。
isqlに入ってる場合は、一度isqlも抜けましょう。

以上です。

2015年4月6日月曜日

Unsupported case in CONVERT エラー

とあるSPARQL文のSELECTする項目に、

abs(xsd:float(?lat) * 1000) AS ?lat 

という記述をしていたら、
うまく動いていたんですが、
ある日突然、
というかSELECT対象のデータを更新したら、
エラーが出るようになったんです。

どうやら、?latに空のデータが入っていると、

xsd:float(?lat)

がコケるみたいで、以下のエラーが出ます。

Virtuoso 22023 Error SR066: Unsupported case in CONVERT (incomplete RDF box -> REAL)

不完全なRDFボックスからREALへの変換はサポートしてません的な・・・ちょっと意味不明です。

対策としては、対象データを文字列に変換する関数str()を挟むようにして、
以下のようにすると

xsd:float(str(?lat))

エラーは出なくなりました。

FILTERの条件のときもstr()必要ですし、str()って何かと便利なんですね。

以上、よろしくお願いいたします。

2015年3月5日木曜日

SPARQLで別グラフをLEFT JOIN, INNER JOINする

SPARQLでSQLみたいなJOINをしたいのです。

まずは、メインクエリとして、1つのグラフをSELECTするSPARQLを書きます。

SELECT *
FROM <graph1>
WHERE {
  ?s <商品コード> ?code
 .?s <商品名> ?name
}
LIMIT 3

商品コードと商品名がとれました。
[code],[name]
A01,にんじん
A02,じゃがいも
A03,ピーマン

次に、他のグラフをLEFT JOINしてみます。
JOINするグラフは、WHEREの中に、サブクエリとして書きます。
連結キーは ?code で、メインクエリとサブクエリで同じ名前にすることで、連結されます。

SELECT *
FROM <graph1>
WHERE {
  ?s <商品コード> ?code
 .?s <商品名> ?name
 .OPTIONAL{
   SELECT ?code ?price
   FROM <graph2>
   WHERE {
     ?s <商品コード> ?code
     .?s <お値段> ?price
   }
 }
}
LIMIT 3

他のグラフからお値段も取ってこれました。
[code],[name],[price]
A01,にんじん,100
A02,じゃがいも,50
A03,ピーマン,


続いて、LEFT JOINをINNER JOINに変えてみます。
サブクエリのOPTIONALを取るだけです。

SELECT *
FROM <graph1>
WHERE {
  ?s <商品コード> ?code
 .?s <商品名> ?name
 .{
   SELECT ?code ?price
   FROM <graph2>
   WHERE {
     ?s <商品コード> ?code
     .?s <お値段> ?price
   }
 }
}
LIMIT 3

こうすると、JOINした先のグラフに無いデータは出てきません。

[code],[name],[price]
A01,にんじん,100
A02,じゃがいも,50

このSPARQLはVirtuoso対応です。
サブクエリを複数書くことで、いくつでも連結できます。
他にも連結方法は有ると思いますが、この方法がわかりやすく、サブクエリ内でFILTERなどもできるので、活用しています。


ついでに、
連結キーが、トリプルでいうところの ?s ?p ?o の ?o で結びつけた例を紹介しましたが、
私が遭遇した、メインクエリの?oとサブクエリの?sで結び付けたい場合は、以下のように書きます。
サブクエリのSELECTの?sを文字列に変換し、別名として?codeを割り当てます。

SELECT *FROM <graph1>
WHERE {
  ?s <商品コード> ?code
 .?s <商品名> ?name
 .{
   SELECT (str(?s) AS ?code) ?price
   FROM <graph2>
   WHERE {
     ?s <お値段> ?price
   }
 }
}
LIMIT 3

これでうまく連結されました。
以上です!