Webアプリ開発エンジニアのための技術情報サイト「テックスコア」

17. 検索実行エンジン(ARQ)

2006.04.17 株式会社四次元データ 中井隆史

17.1. ARQ概要

ARQ とは Jena のフレームワーク上で使用可能な検索エンジンのことです。 ARQ は SPARQLRDQLなどの検索言語をサポートしています。 以前は開発途中であったため ARQ と Jena は別々に配布されており、 Jenaが標準でサポートしていたのは RDQL だけでした。 その後 Jena のバージョンが 2.3 になるとともに ARQ が付属するようになったため、 より強力な SPAQL による検索を行うことができるようになりました。

SPARQL は RDQL をベースに発展させたより強力な言語で、 現在も W3C の Working Draft として規格化が続けられています。 構文など SPARQL 自体については、トップカテゴリのセマンティックWeb以下にカテゴリを設けて解説しています。 ここからは ARQ 上で SPARQL による検索を実行する方法を中心に解説します。

17.2. 検索の実行の流れ

ARQ を使って検索を行うときに関係するクラスやインタフェースには、主に次のようなものです。

com.hp.hpl.jena.query.Query
クエリそのものを表すクラスです。
com.hp.hpl.jena.query.QueryFactory
ファイルや文字列として表されたクエリをパースし、Query のオブジェクトを生成するためのクラスです。
com.hp.hpl.jena.query.QueryExecution
検索の実行を行う機能を提供します。このインターフェースのオブジェクトは、検索の実行一回分に対応します。
com.hp.hpl.jena.query.QueryExecutionFactory
QueryExecutionを実装したオブジェクトを生成します。

SELECT の結果を処理するためには、さらに次の3つを用います。

com.hp.hpl.jena.query.ResultSet
得られた結果を順に取り出すための Iterator です。個々の結果は QuerySolution を実装しています。
com.hp.hpl.jena.query.QuerySolution
結果を表形式で表した場合のレコードひとつに対応します。個々の変数の値をバインディングしオブジェクトとして取り出せるようにする機能を提供します。
com.hp.hpl.jena.query.ResultSetFormatter
ResultSetを表形式やXML、RDFなどの形式にフォーマットして出力するためのクラスです。

検索の準備から実行、結果の取得までの基本的な流れは次のようになります。

  1. クエリを QueryFactory に与えて Query オブジェクトを作成する。
  2. Query オブジェクト(と From 節を省略している場合は対象の Model オブジェクト)を引数にして QueryExecution オブジェクトを作成する。
  3. クエリの種類に応じたメソッドを呼んで検索を実行する。
  4. 結果を必要に応じて取り出し処理する。
  5. QueryExecution.close() を呼んで問い合わせ処理を終える。

では実際にSPARQLを使って問い合わせを実行し結果出力するプログラムを見てみましょう。 次のソースは SELECT クエリを実行するサンプルコードです。

サンプルクエリ
PREFIX  foaf: <http://xmlns.com/foaf/0.1/>
SELECT ?x ?name ?mbox "
WHERE { ?x foaf:name ?name . 
        ?x foaf:mbox ?mbox }
サンプルコード
1:  import com.hp.hpl.jena.query.Query;
2:  import com.hp.hpl.jena.query.QueryExecution;
3:  import com.hp.hpl.jena.query.QueryExecutionFactory;
4:  import com.hp.hpl.jena.query.QueryFactory;
5:  import com.hp.hpl.jena.query.QuerySolution;
6:  import com.hp.hpl.jena.query.ResultSet;
7:  import com.hp.hpl.jena.rdf.model.Literal;
8:  import com.hp.hpl.jena.rdf.model.Model;
9:  import com.hp.hpl.jena.rdf.model.Resource;
10: import com.hp.hpl.jena.util.FileManager;
11: 
12: public class SPARQLSample {
13: 
14:    public static void main(String[] args) {
15:       Model model = FileManager.get().loadModel(
16:              "file:foaf_example.rdf");
17: 
18:       String queryString = 
19:            "PREFIX  foaf: <http://xmlns.com/foaf/0.1/> "
20:          + "SELECT ?name ?mbox "
21:          + "WHERE { ?x foaf:name ?name . "
22:          + "?x foaf:mbox ?mbox }";
23: 
24:       Query query = QueryFactory.create(queryString);
25:       QueryExecution qexec = 
26:                QueryExecutionFactory.create(query, model);
27:       ResultSet results = qexec.execSelect();
28: 
29:       try {
30:          while (results.hasNext()) {
31:             QuerySolution qs = results.nextSolution();
32:             Literal name = (Literal) qs.get("name");
33:             Resource mbox = (Resource) qs.get("mbox");
34: 
35:             System.out.println(name + ":" + mbox);
36:          }
37:       } finally {qexec.close();}
38:    }
39: }

18-22行目が文字列で表現された実際のクエリです。 24行目で、QueryFactory.create メソッドにこの文字列を引数にして Query オブジェクトを生成します。 次に25-6行目のように QueryExecutionFactory.create メソッドを使用して実行エンジンを作成します。 クエリに FROM 節が無い場合は 対象の RDF も引数として与えます。 その後 25行目のように execSelect() メソッドが呼ばれると検索が実行され ResultSet 型の戻り値が返ってきます。

ResultSet は Iterator を実装していてクエリに合致した変数の組み合わせを複数含んでいます。 そこで 30 行目から 36 行目のようにループを使って一つずつ結果を取り出して処理します。 ResultSet の要素は全て QuerySolution オブジェクトです。 QuerySolution オブジェクトはリソースやプロパティ、リテラルを クエリで指定した各変数に対し一つずつ持っています。 この値は get(String s) メソッドに変数名を引数として与えることで得ることができます。 このときはクエリの場合とは異なり"?"はつけません。 対応するインタフェース(今回の場合はResourceとLiteral)型の変数で受け取ると、 必要なオブジェクトを得ることができます。 リソースかリテラルか分からない場合には RDFNode で受け取ったあとに canAs() メソッドや instanceof 演算子などを利用して調べる必要があります。

最後に37行目で qexec の close メソッドを実行し検索処理を終了します。 これで一連の処理が終了します。

入力に使われている file:foaf_example.rdf が 次のような RDF であるとすると結果下のようになります。

サンプルRDF
<?xml version="1.0"?>
<rdf:RDF
    xmlns:foaf="http://xmlns.com/foaf/0.1/"
    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" >
  <rdf:Description rdf:nodeID="A0">
    <foaf:name>四次元太郎</foaf:name>
    <foaf:mbox rdf:resource="mailto:yonta@4dd.co.jp"/>
  </rdf:Description>
  <rdf:Description rdf:nodeID="A1">
    <foaf:name>四次元次郎</foaf:name>
    <foaf:mbox rdf:resource="mailto:jiro@4dd.co.jp"/>
  </rdf:Description>
</rdf:RDF>
結果
四次元太郎:mailto:yonta@4dd.co.jp
四次元次郎:mailto:jiro@4dd.co.jp

17.3. クエリの種類とメソッドの関係

サンプルプログラムでは SELECT をクエリの代表例としてあげましたが他の種類のクエリの実行も可能です。 SELECT に対しサンプルプログラムの 25 行目で execSelect メソッドを使用したように、 クエリの種類に応じたメソッドを使用します。

クエリ 対応するメソッド
SELECT com.hp.hpl.jena.query.ResultSet execSelect()
CONSTRUCT com.hp.hpl.jena.rdf.model.Model execConstruct()
DESCRIBE com.hp.hpl.jena.rdf.model.Model execDescribe()
ASK boolean execAsk()

execSelect() 以外については戻り値が特殊な型をしているわけでは無いので、結果を利用するのは比較的容易でしょう。 いずれにせよクエリの種類を自動判別をするわけではないという点には注意が必要です。



前のページへ TECHSCOREのTOPページへ 次のページへ
TECHSCORE PR
PR
PR
PR
PR
PR

techscore(トップページへ)
TECHSCORE書店
TECHSCOREトップページJavaSQLXMLリッチクライアントモデリングセマンティックWebその他技術Tuigwaa