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

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

2014年10月7日火曜日

ソートすると1万件以降が表示できない

ORDER BY でソートをかけて、1万件目以降のデータを表示しようとすると、以下の様なエラーがでます。

ERROR : Virtuoso 22023 Error SR353: Sorted TOP clause specifies more then 10010 rows to sort. Only 10000 are allowed. Either decrease the offset and/or row count or use a scrollable cursor

LIMITとOFFSETの組み合わせで、1万1件目のみ表示にしても、とにかく1万件目以降を表示しようとするとダメです。

これを回避するには、virtuoso.iniの[Parameters]セクションにMaxTopSortedRowsというパラメータを追加しなさいと、いたるところで書かれています。

http://virtuoso.openlinksw.com/dataspace/doc/dav/wiki/Main/VirtSparqlCxmlFacetPivotBridge

でも、私の環境ではこのパラメータを認識せず、改善しませんでした。

さらに検索したところ、クエリを別にすればよいという裏ワザを見つけました。
これでうまくいきました。

https://github.com/mff-uk/DPUs/issues/78


具体的には、こんなかんじで、いつものSELECTはORDER BYまでにして、それを囲む感じで LIMITとOFFSET をつけます。

変更前
SELECT ?a ?b ?c WHERE {?a ?b ?c} ORDER BY ?a
LIMIT 10 OFFSET 10000

変更後
SELECT * WHERE {
  SELECT ?a ?b ?c WHERE {?a ?b ?c} ORDER BY ?a
}
LIMIT 10 OFFSET 10000

これでうまくいきました。


2014年7月29日火曜日

グラフの操作

SPARQLにはグラフをまるごと操作する方法が用意されています。

  • CREATEオペレーションは、空のグラフをサポートしているストアに新しいグラフを作成します。
  • DROPオペレーションは、グラフとその内容のすべてを削除します。
  • COPYオペレーションは、別のグラフのコピーを含むようにグラフを修正します。
  • MOVEオペレーションは、あるグラフから別のグラフにすべてのデータを移動させます。
  • ADDオペレーションは、あるグラフのすべてのデータを別のグラフへと再作成させます。



ここに詳しく書いてます。
http://www.asahi-net.or.jp/~ax2s-kmtn/internet/rdf/REC-sparql11-update-20130321.html#graphManagement

2014年5月19日月曜日

Virtuoso 42000 Error

長いSPARQL文を投げると、下記のようなエラーが出る場合がある。

Virtuoso 42000 Error The estimated execution time 1498 (sec) exceeds the limit of 400 (sec).

日本語訳するとこうで、

ビルトーソ 42000 エラー 推定実行時間1498(秒)は、400(秒)の制限を超えています。

これはおそらく、
「このSPARQLはクソ難しいので実行すると1498秒もかかりそうだからやりたくないよ~」
といっているのだと思う。

virtuoso.ini の中に、MaxQueryCostEstimationTime という設定項目があるので、
そこの値を大きくしてあげれば、長いSPARQL文も実行できるようになる。

ちなみにデフォルトは 400 でした。
適当に4000にしてみました。

MaxQueryCostEstimationTime = 400   ; in seconds
  ↓
MaxQueryCostEstimationTime = 4000   ; in seconds




2014/08/20 追記
少々上げたぐらいではすぐに同じエラーにひっかかるので無制限にしてしまったほうが楽、とうことで、行自体をコメントアウトすると無制限になります。
 ;MaxQueryCostEstimationTime = 4000   ; in seconds


 下記のページ参考になりました。ありがとうございます。
http://wiki.lifesciencedb.jp/mw/index.php/BH12.12/SPARQLthon8/TogoGenome-Virtuoso7

2014年4月16日水曜日

よくつかうSPARQLサンプル集

とりあえずトリプルが何件入ってるか知りたい
SELECT count(*) WHERE { ?s ?p ?o }
 

とりあえずどんなトリプルが入っているか見たい
SELECT * WHERE { ?s ?p ?o } LIMIT 500

グラフ毎の件数を集計して見たい
SELECT ?g count(?g) WHERE {GRAPH ?g {?s ?p ?o}} GROUP BY ?g

あるグラフ配下のトリプルだけを見たい(何のグラフがあるかは一つ上↑のSPAQLで)
SELECT * WHERE { GRAPH <あるグラフ> {?s ?p ?o }}

aomoriが含まれるトリプルを探したい(主語から探す)
SELECT * { GRAPH ?g { ?s ?p ?o . FILTER( contains(str(?s),'aomori') ) }}

titleが含まれるトリプルを探したい(述語から探す)
SELECT * { GRAPH ?g { ?s ?p ?o . FILTER( contains(str(?p),'title') ) }}

青森県が含まれるトリプルを探したい(目的語から探す)
SELECT * { GRAPH ?g { ?s ?p ?o . FILTER( contains(str(?o),'青森県') ) }}

グラフ完全一致で探す
SELECT * { GRAPH <グラフ> {?s ?p ?o}}

主語完全一致で探す
SELECT * { GRAPH ?g {<主語> ?p ?o}}

述語完全一致で探す
SELECT * { GRAPH ?g {?s <述語> ?o}}

目的語完全一致で探す
SELECT * { GRAPH ?g {?s ?p '目的語'}}

目的語完全一致で探す(言語指定あり)
SELECT * { GRAPH ?g {?s ?p '目的語'@ja}}


以下のサイトでなどでお試しできます。(レスポンス悪いです)
http://dbpedia.org/sparql
http://ja.dbpedia.org/sparql