virtuoso事始め(Ubuntu編)

ローカルでSPARQL Endpointを使用したかったので、[DBpedia](http://ja.dbpedia.org/)でも使用されている[virtuoso](https://virtuoso.openlinksw.com/) (読み：ビルトーソ, ヴィルトゥオーソ, バーチュオーソー)の環境を構築して、構築したSPARQL Endpointに対して、SPARQLクエリで検索・更新・削除する方法をまとめました。

# 導入環境

* 仮想マシン
* Ubuntu：16.04.1 LTS
* virtuoso：6.1.6.3127

# 環境構築

## インストール

* パッケージが配布されているので、そいつを使う
* パッケージとして配布されているのはバージョン6

```
$ sudo apt update
$ sudo apt install virtuoso-opensource -y
```
画面にdefault Userのdefault passwordを変更するか聞かれるが、今回は変更せずにOKを選択する

![ビルトソキャプチャ1.JPG](https://qiita-image-store.s3.amazonaws.com/0/92620/71428daa-d4c1-3119-9498-6242d3010131.jpeg)

これでインストールは終わり
コマンドに`virtuoso-t`が追加されていればOK


## virtuosoの起動

* virtuoso.iniがあるディレクトリまで移動する
  - 特に問題が無ければ`/etc/virtuoso-opensource-6.1`以下にvirtuoso.iniがあります
* 起動コマンドの実行
  * `-f`は`foreground`で実行するオプション
  * `-d`はデバック情報を表示するオプション
 
```
$ cd /etc/virtuoso-opensource-6.1
$ sudo virtuoso-t -df
```
## 動作確認

### ブラウザからアクセス

*  以下のURLでHomeにアクセスできます
  - `http://<server_IP>:8890`

![ビルトソキャプチャ2.JPG](https://qiita-image-store.s3.amazonaws.com/0/92620/8d2edb02-31b3-f30b-febf-2e3e2be6ecc6.jpeg)

### Virtuoso Conductorにログイン

* Home画面の左側にある`Conductor`のリンクをクリックする
* `user name`と`password`を入力する場所があるのでデフォルトのユーザ名、パスワードを入力するとログインが完了する
  - user: dba
  - password: dba

![ビルトソキャプチャ5.JPG](https://qiita-image-store.s3.amazonaws.com/0/92620/2864c447-2681-39df-63f6-3f49f8fb83ad.jpeg)



### ブラウザからSPARQLクエリを投げる

* 以下のURLからConductorへのログインなしでSPARQLクエリを投げることができます
  - http://<server_IP>:8890/sparql

![ビルトソキャプチャ3.JPG](https://qiita-image-store.s3.amazonaws.com/0/92620/ac855b27-0db6-980d-5552-369872d6ab9d.jpeg)

### CUIからSPARQLクエリを投げる

* `isql-vt`コマンドを使用することで、対話形式でSPARQLクエリを投げることができる
* 通常のSPARQLクエリの前に、SPARQLと入力してからクエリを書く。

```
$ isql-vt 1111 dba dba
SQL> SPARQL SELECT * WHERE {?s ?p ?o};
```

# Local SPARQL Endpoint構築

## RDF(Turtle)ファイルをブラウザからimport

* 1.virtuoso Homeから、Conductorに入りdbaユーザからログインする。
* 2.ログインできたら、タブの中にある[Linked Data]をクリック(下記画像の赤く囲ったところ)

![ビルトソキャプチャ7.jpg](https://qiita-image-store.s3.amazonaws.com/0/92620/379f727d-5452-743c-5ffc-f560ab29b246.jpeg)

* 3.もう一段タブが表示されるので、新たに表示されたタブ中の[Quad Store Upload]をクリック

![ビルトソキャプチャ8.jpg](https://qiita-image-store.s3.amazonaws.com/0/92620/cef711bd-9f6b-6620-ff21-0a13a897fff5.jpeg)

* 4."File"にチェックを入れ、Uploadしたいファイルを選択する
 - この時ファイルの文字コードが`utf-8`になっているか確認しておく
 - GraphのIRIを独自のものにしたい場合は"Named Graph IRI"を編集する
 - 今回は`http://localhost:8890/TEST/`という名前でグラフIRIを設定しました

![ビルトソキャプチャ9.jpg](https://qiita-image-store.s3.amazonaws.com/0/92620/7fac4e3d-41dd-8fa8-68cb-75d917fb3e29.jpeg)

* 5. [Upload]ボタンを押したらアップロード完了!

### アップロードできているか確認

SPARQLクエリを投げてみて、指定したGraph IRIでアップロードできているか確認します

#### ブラウザからクエリを投げる場合

* Default Data Set Nameに先ほど設定したGraph URI(今回だと`http://localhost:8890/TEST/`)を入力してからクエリを投げてみてください。

![ビルトソキャプチャ10.jpg](https://qiita-image-store.s3.amazonaws.com/0/92620/a815b31d-99b7-8690-14ed-30f179e15cc8.jpeg)

#### CUIからクエリを投げる場合

* SELECT文の後に`FROM <Graph URI>`を追加します

```
# isql-vt 1111 dba dba
SQL> SPARQL SELECT * FROM <http://localhost:8890/DAV> WHERE {?s ?p ?o};
```

## SPARQLクエリでデータをUPDATE

SPARQLクエリでデータをUPDATEできるように設定します

### Update許可設定

初期状態だとSPARQLで、UPDATEやINSERT,DELETE系の処理はできないようになっていおり、実行すると以下のように権限がないと言われてしまいます。

```
Virtuoso 42000 Error SR186:SECURITY: No permission to execute procedure DB.DBA.SPARQL_INSERT_DICT_CONTENT~~以下略~~
```

Update系の処理をするためには、Update権限をするための権限を設定する必要があります。この設定はブラウザから簡単にできます。

* 1. Virtuoso Conductorにログイン
* 2. System Adminタブをクリック
* 3. 2段目のタブに出てきたUser Accountsをクリック

![ビルトソキャプチャ11.jpg](https://qiita-image-store.s3.amazonaws.com/0/92620/497a0e8a-6f55-8d9d-5e22-bd48ee419728.jpeg)

* 4."SPARQL" 行の `edit` をクリック

![ビルトソキャプチャ12.jpg](https://qiita-image-store.s3.amazonaws.com/0/92620/f842d0c0-6a02-23b5-6faa-ec9d15a321e8.jpeg)

* 5.`Account roles` の `SPARQL_UPDATE` を `Selected field`(右側)に持っていく
![ビルトソキャプチャ13.jpg](https://qiita-image-store.s3.amazonaws.com/0/92620/366e9f6f-0a8b-a543-8f7e-36243a4094d0.jpeg)

* 6.忘れずに[save]ボタンを押せば設定完了です

#### Update系の処理を実行してみる

* データをINSERTしてDELETEできるか試してみます

```
SQL> sparql select distinct * FROM <http://localhost:8890/TEST/> where {?s ?p ?o .};
s                                                                                 p                                                                                 o
LONG VARCHAR                                                                      LONG VARCHAR                                                                      LONG VARCHAR
_______________________________________________________________________________

http://example.org/#green-goblin                                                  http://www.w3.org/1999/02/22-rdf-syntax-ns#type                                   http://xmlns.com/foaf/0.1/Person
http://example.org/#spiderman                                                     http://www.w3.org/1999/02/22-rdf-syntax-ns#type                                   http://xmlns.com/foaf/0.1/Person
http://example.org/#green-goblin                                                  http://www.perceive.net/schemas/relationship/enemyOf                              http://example.org/#spiderman
http://example.org/#spiderman                                                     http://www.perceive.net/schemas/relationship/enemyOf                              http://example.org/#green-goblin
http://example.org/#green-goblin                                                  http://xmlns.com/foaf/0.1/name                                                    Green Goblin
http://example.org/#spiderman                                                     http://xmlns.com/foaf/0.1/name                                                    Spiderman
http://example.org/#spiderman                                                     http://xmlns.com/foaf/0.1/name                                                    ▒X▒u▒|▒▒▒r▒u▒{-▒▒▒p▒▒▒{
SQL> SPARQL INSERT{ GRAPH <http://localhost:8890/TEST/> { <http://example.org/#spiderman> foaf:name "地獄からの使者"}}
T;
Done. -- 5 msec.
SQL> sparql select distinct * FROM <http://localhost:8890/TEST/> where {?s ?p ?o .};
s                                                                                 p                                                                                 o
LONG VARCHAR                                                                      LONG VARCHAR                                                                      LONG VARCHAR
_______________________________________________________________________________

http://example.org/#green-goblin                                                  http://www.w3.org/1999/02/22-rdf-syntax-ns#type                                   http://xmlns.com/foaf/0.1/Person
http://example.org/#spiderman                                                     http://www.w3.org/1999/02/22-rdf-syntax-ns#type                                   http://xmlns.com/foaf/0.1/Person
http://example.org/#green-goblin                                                  http://www.perceive.net/schemas/relationship/enemyOf                              http://example.org/#spiderman
http://example.org/#spiderman                                                     http://www.perceive.net/schemas/relationship/enemyOf                              http://example.org/#green-goblin
http://example.org/#green-goblin                                                  http://xmlns.com/foaf/0.1/name                                                    Green Goblin
http://example.org/#spiderman                                                     http://xmlns.com/foaf/0.1/name                                                    Spiderman
http://example.org/#spiderman                                                     http://xmlns.com/foaf/0.1/name                                                    ▒X▒u▒|▒▒▒r▒u▒{-▒▒▒p▒▒▒{
http://example.org/#spiderman                                                     http://xmlns.com/foaf/0.1/name                                                    地獄からの使者

8 Rows. -- 1 msec.
SQL> DELETE{ GRAPH <http://localhost:8890/TEST/> { <http://example.org/#spiderman> foaf:name "地獄からの使者"}};
SQL> SPARQL DELETE{ GRAPH <http://localhost:8890/TEST/> { <http://example.org/#spiderman> foaf:name "地獄からの使者"}};

Done. -- 3 msec.
SQL> sparql select distinct * FROM <http://localhost:8890/TEST/> where {?s ?p ?o .};
s                                                                                 p                                                                                 o
LONG VARCHAR                                                                      LONG VARCHAR                                                                      LONG VARCHAR
_______________________________________________________________________________

http://example.org/#green-goblin                                                  http://www.w3.org/1999/02/22-rdf-syntax-ns#type                                   http://xmlns.com/foaf/0.1/Person
http://example.org/#spiderman                                                     http://www.w3.org/1999/02/22-rdf-syntax-ns#type                                   http://xmlns.com/foaf/0.1/Person
http://example.org/#green-goblin                                                  http://www.perceive.net/schemas/relationship/enemyOf                              http://example.org/#spiderman
http://example.org/#spiderman                                                     http://www.perceive.net/schemas/relationship/enemyOf                              http://example.org/#green-goblin
http://example.org/#green-goblin                                                  http://xmlns.com/foaf/0.1/name                                                    Green Goblin
http://example.org/#spiderman                                                     http://xmlns.com/foaf/0.1/name                                                    Spiderman
http://example.org/#spiderman                                                     http://xmlns.com/foaf/0.1/name                                                    ▒X▒u▒|▒▒▒r▒u▒{-▒▒▒p▒▒▒{

7 Rows. -- 1 msec.
SQL>

```

# 終わりに

以上、virtuoso6でSPARQL Endpointを作成してSPARQLクエリから検索、更新削除ができるようになりました。
本当は、CentOSでvirtuosoのバージョン7を動かしたかったのですが上手くビルドできなかったので途中であきらめていましたが、さっきやってみたらすんなり動いたのでそっちの手順も近いうちにまとめたいと思います。