Open16

data/rdf

kwikwi

wikibase で rdf/turtle 出力するとき。/wiki/Special:EntityData/Q1.ttl などにアクセスすればよい。

wd:p: などの prefix を固定するときは、次のように conceptBaseUri を指定するとよい

$wgWBRepoSettings["conceptBaseUri"] = "https://example.jp/entity/";

data: などの自己参照は、Wikibase extension レベルでどうこうするところはなさそうで、次のように mediawiki 設定を変更する。

$wgCanonicalServer = "https://example.jp";

ただし https://phabricator.wikimedia.org/T241975 でまた挙動がかわる

kwikwi

quad が使われる理由:tripleで知識が得られたとして、次にその主張を信じてよいのかが問題になる。その検証には使用したtripleの出典が問題になる。自然と triple に出典・来歴をくっつけた形で扱うことが多くなるため、quad という形式で管理すると都合がよい。
実装上も、例えば更新頻度の異なるデータセットを分けて管理したい場合、名前空間のようなもので分離しておきたいと思うだろう。そういったときにもquadが有効になる。つきつめるとこれもデータの出元の問題となる。
出典付き triple は triple with provenance と呼ばれ、例えば blazegraph の設定例でも TRIPLES_MODE, TRIPLES_MODE_WITH_PROVENANCE, QUADS_MODE が用意されていたりする。
https://github.com/blazegraph/database/wiki/Blazegraph_FAQ

kwikwi

あまり明言されない事をメモしておく

  • クラス情報は必須ではない。無くてもデータに SPARQL できる。
  • オントロジーでいうところの「推論」は一般的な意味の推論ではなく、コンパイラの「型推論」の意味。
  • rdf:type をはじめとするクラス設計は、達成したい目標に向かってデータ作成者が設計する。一般的な話として、目標から外れた過剰な設計は必要ない。
  • プログラミング言語で、単一継承、多重継承、ミックスインといった概念がある。これらと対応させて rdf:type を考えると良い。
  • 初期段階ではデータベースやサーチエンジンは必要ない。turtle あるいは trig のプレーンテキストのファイルに SPARQL を行うシステムで必要十分。
  • quad store は provenance に有効で、linked data として使うときに役に立つ。
  • RDF は triple や quad という概念。Linked data はデータ結合をする世界観。二つのものは並列するものではなく、そもそも指し示しているものが異なる。
  • RDF / Linked Data の機能や理念と実際のデータの乖離に消耗することはよくある。しかしながら Linked data が有効な局面は確かに存在するので、必要になったときにはじめて必要なだけ使えばよい。
kwikwi

Datasetという用語は、最初SPARQLで導入され、RDF関連の様々なところで顔を覗かせる。ただしDatasetはコンテキストによって意味するところが変わることに注意。

Virtuossoでは、Quadstoreであり、Datasetはデータを分割するもの。SPARQL query 時に名前を指定せずに query すると、全体をクエリすることができる。名前を指定すると、そのdataset内のgraphのみが検索される。SPARQL 1.1 updateのインターフェースからは、名前なしのDefault datasetにtripleを保存することはできない(*1)。DELETE もdatasetの指定が必須で、どういうモデルを考えているのかがうかがえる(*2)。

*1) https://github.com/openlink/virtuoso-opensource/issues/417
*2) https://github.com/openlink/virtuoso-opensource/issues/215#issuecomment-48845476

kwikwi

rdflib sparql 1.1 update の話

SPARQLWrapper が先行して対応し、rdflib の SPARQL 対応はゆっくりと進んできた。SPARQL 1.1 update は rdflib 本体でもできるようになってきた。

ただし現時点での SPARQLUpdateStore は少し変な状況にある。SPARQLConnector.update の実装を引き継げばいいように思えるのだけれど、独自な実装をしている。使う場合は database transaction のように commit, rollback で終わらせること。でないとゴミが残って、続く処理でおかしなことになる。

from rdflib import URIRef, Graph
g = Graph("SPARQLUpdateStore", "http://example.org/defaultGraphUri")
g.open("http://example.org/sparqlendpoint")
# USE add()
try:
  g.add((URIRef("a:"), URIRef("b:"), URIRef("c:")))
  g.commit()
except:
  g.rollback()
# OR, update()
try:
  g.update("INSERT DATA { <a:> <b:> <c:> . }")
  g.commit()
except:
  g.rollback()

virtuoso は HTTP GET method で SPARQL 1.1 Update が実行できる(組み込みWebUIもこれを使ってる)。だから rdflib.Graph.update ではなく rdflib.Graph.query で SPARQL 1.1 Update が実行できて、SPARQLUpdateStore を回避することも可能。

kwikwi

fuseki/Jena の dockerfile は maven repo 経由で取得できるらしい(出典)。具体的な手順が書いてなかったけれども、次のコマンドが便利。

mvn dependency:get -Dartifact=org.apache.jena:jena-fuseki-docker:LATEST:zip -Ddest=.

あるいは普通に wget でダウンロードしてもよさそう。

SOH cli utility は apache-jena-fuseki binary distribution(zip) をダウンロードして展開して PATH を通せばよさそう。ruby が必要。

kwikwi

fuseki/jenaはSPARQL構文に厳密。virtuosoは、アルアルなエラーは見逃して解釈してくれる。おそらくサポートの都合もあって、歴史的なものを引きずってメンテナンスしてる。ある意味では偉い。

virtuoso は例えば次の構文を許す。

SELECT ?a, ?b WHERE { # 正しくは `SELECT ?a ?b`
 ?a ?b ?c . 
} ORDER BY ?b, ?c # 正しくは ?b ?c

あるいは、SPARQL query で SPARQL update を流しても受け入れる。本来update=でupdate構文を送るところを、query= の中身として送っても処理される。

kwikwi

fuseki/jena を高可用性(HA)の構成にしようとすると、rdf-deltaの拡張版が見つかる。
https://afs.github.io/rdf-delta/ha-fuseki.html
https://github.com/afs/rdf-delta

delta-fuseki-server を実行すると、rdf の更新時に rdf patch 形式の差分を生成し、delta-server に送り込む。delta-server は全ての変更履歴を保持していて、ジャーナリングを行う。delta-fuseki-server はジャーナルから rdf を構築しなおして query に備える。

single でも動作させられる。HAにするには各ポイントを冗長化させる。delta-server は zookeeper で quorum を組んで動作する。

kwikwi

SemanticMediaWiki の SPARQLStore 設定、現時点(2023-06)では、正直 "default" connector だけでいい気がする。"virtuoso" も "fuseki" も使わなくていいんじゃない…?
ただし"data"エンドポイントだけは、SemanticMediaWiki側がぶっ壊れているので空文字で無効化しておくこと。
https://www.semantic-mediawiki.org/wiki/Help:SPARQLStore

kwikwi

rdflib SPARQL endpoint が自己署名証明書な HTTPS だった時の話。一番簡単な「検証無視」な設定はデフォルトファクトリを置き換える方法。

import ssl
ssl._create_default_https_context = ssl._create_unverified_context
import rdflib
g=rdflib.Graph("SPARQLUpdateStore")
g.open("https://selfsigned.sparql.endpoint.example.org/")
g.query('''
SELECT * WHERE { ?s ?p ?o . }
''')

https://github.com/RDFLib/sparqlwrapper/issues/168

kwikwi

jena fuseki を使っていて、トリプルを保存したはずなのに、どっかに行ってしまったと思った時。ひょっとして default graph に保存されているかも。

jena fuseki は quad store で、特殊機能として named graph を一つにまとめて見せる unionDefaultGraph という機能 がある。注意点としては、名前のない default graph は Union されないという点。

jena fuseki の SPARQL は一般的に使われる query 以外に、SPARQL を拡張した SPARQL 1.1 UPDATE である updateSPARQL Graph store protocol (GSP)gsp-r, gsp-rwサポートしている。

迷子になったときは次を試してみるとよい

  • GSP get でデフォルトグラフを取得する
    • s-get コマンドで operation=gsp-r なエンドポイントに問い合わせる
  • デフォルトグラフを明示的に指定して SPARQL クエリする
    • 特殊 URI である urn:x-arq:DefaultGraph を使う
SELECT * WHERE { GRAPH <urn:x-arq:DefaultGraph> { ?s ?p ?o . } }
kwikwi

SPARUL は、もともと hp で jena の機能として開発されていた SPARQL の拡張で、SPARQL/Update と表記されたりもするもの。

そのうちに w3c で標準化が進み、SPARQL-Update となった。SPARUL は祖先のバージョン違いと考えればよい。

ちなみに jena は hp から apache foundation に移管された