2012-03-20 14 views
11

おそらくこれには簡単に答えることができますが、私はそれを見つけるためにGoogleクエリを定式化する方法を見つけられません。SPARQLの構築クエリで空ノードを再帰的に展開するには?

私は空のノードを含むデータセットに対してSPARQL構文を作成しています。私は

CONSTRUCT {?x ?y ?z .} WHERE {?x ?y ?z .}

のようなクエリを行うのであれば次に私の結果の一つは、次のようになります。

_:Node nm:has nm:Hats

のすべての場合は問題あり

nm:John nm:owns _:Node

トリプルは何らかの理由でクエリの結果にもなりません(なぜ私はrdfのようなパーサーを使用しているのでPythonのためのlibは本当にbnodeがついていないのが好きです)。

オリジナルのCONSTRUCTクエリを書き込んで、新しいノードにbノードが残っていないように、すべてのbノードの結果に再帰的に追加する方法はありますか?

+2

。 [Sparqlクエリでrdfs:class定義を構成するすべてのトリプルを再帰的に返す](http://answers.semanticweb.com/questions/26220/sparql-query-to-return-all-triples-recursively- make-up-an-rdfsclass-definition)(そしておそらく[SPARQLの簡潔なバウンド記述の実装](http://answers.semanticweb.com/questions/20361/implementing-concise-bounded-description-in-paran) )。 –

+1

前のコメントの回答の背景にある考え方は、プロパティパス内の述語として効果的に機能する*新しいプロパティ*を作成できるということです。たとえば、各IRIノードiに対して、3つの「i selfIRI i」を追加します。次に、 "?x p/selfIRI?y"のようなパスを記述すると、?yがIRIノードであることが保証されます。 –

答えて

10

再帰ができません。私が考えることのできる最も近いものはSPARQL 1.1 property pathsです(注:そのバージョンは古いです)が、bノードテストは利用できません(afaik)。

あなただけの末尾bnodesとの文を削除できます。

CONSTRUCT {?x ?y ?z .} WHERE 
{ 
    ?x ?y ?z . 
    FILTER (!isBlank(?z)) 
} 

または次のビットをフェッチあなたの運を試してみてください。

CONSTRUCT {?x ?y ?z . ?z ?w ?v } WHERE 
{ 
    ?x ?y ?z . 
    OPTIONAL { 
    ?z ?w ?v 
    FILTER (isBlank(?z) && !isBlank(?v)) 
    } 
} 

(最後の問い合わせがところで、かなり過酷であること)

DESCRIBEを使う方が良いかもしれませんが、これはしばしばbノードをスキップします。

+0

ありがとうございました。私の現在の計画では、より深いレベルへの再帰を心配することなく2レベルのクエリを使用しています。 isBlankフィルタが役立つかもしれませんが、SPARQLはラインごとにフィルタを実行する前にSPARQLがプレフィルタサブグラフ全体を具体化しているように見えるので、FILTERは実際に性能を低下させるようです。したがって、フィルタされていないサブグラフが小さい場合を除き、フィルタクエリは非常に集中的です。 – rogueleaderr

+2

「SPARQLはプレフィルタサブグラフ全体を実現しています...」とは言えません。異なるSPARQLエンジンの実装には、さまざまな長所と短所を持つ異なるアルゴリズムがあります。使用しているライブラリのバージョンによっても異なります。 –

3

ユーザ205512が示唆しているように、このグラブを再帰的に実行することは不可能であり、任意のレベルを使用してデータをノードに取得することは、自明ではないサイズのデータ​​ベースでは実現できません。

ノード自体は、ローカルスコープ、結果セット、またはファイルにスコープされています。 BNodeが構文解析から得られるか、結果セットからデータベースで使用されるものと同じIDであるという保証はありません(ただし、一部のデータベースでは照会結果に対してこのことが保証されます)。さらに、 "select?s where where {?s?p::bnodeid1}"のようなクエリは、 "select?where {?s?p?}"と同じです - この場合、bnodeは変数として扱われます"idが 'bnodeid1'のものではなく" "この設計の奇妙な点は、bnodeを照会するのが難しくなるため、データを管理している場合は、それらを使用しないことをお勧めします。それ以外の場合はbnodeとなるリソースの名前を生成することは難しくありません。名前付きリソースvnodeはクエリ中にオーバーヘッドを増加させません。

これは、データを収集して取得するのに役立つわけではありませんが、一般的なクエリを実行することはお勧めしません。彼らはうまくスケールされず、通常はあなたが望むまたは必要以上に多くを返します。私はより多くの指示された質問をすることをお勧めします。あなたの元の構築クエリはデータベース全体の内容をプルダウンしますが、これは一般的にあなたが望むものではありません。

最後に、説明は便利ですが、標準的な実装はありません。 SPARQL仕様では特定の動作が定義されていないため、返される内容はデータベースベンダーに委ねられているため、異なる場合があります。これにより、アプリケーションで異なるデータベースを使用しようとすると、コードの移植性が低下する可能性があります。特定の動作を説明外にしたい場合は、自分で実装するのが最良です。 Bnodeのいくつかの頭痛に遭遇することができますが、リソースの簡潔な境界に置かれた説明のような何かを行うのは簡単なコードです。

+1

マイケルにお返事ありがとうございます。私のサンプルクエリは少し不正確でした...私が実際にやろうとしているのは、ダウンロードしたデータセット内の特定のエンティティに関するすべての情報を引き出すことです。しかし、データセットには、 "Johnは1234の作成者でした"というようなエントリが含まれています。だから私は私の代わりに、2レベルのクエリを使用して、それがパフォーマンスを圧倒しないことを望んでいる、またはすべてのbノードの名前をデータベースを再構築するだけだと思います。 SPARQL仕様ではこれを強くサポートしているようですが、これは特に珍しい問題ではないようです。 – rogueleaderr

1

Ruby RDF.rbライブラリ(RDF :: Graphオブジェクトの便利なメソッドを持つSPARQLクエリを可能にする)に関しては、空白ノードを拡張する必要があります。あなたはCONSTRUCTクエリを実行し、その反対SPARQLクエリを実行することができる方法でこれをやっている場合は、あなたが実際に* * SPARQLクエリを使用して簡潔な-有界記述(CBD)を取得することができます

rdf_type = RDF::SCHEMA.Person # for example 
rdf.query([nil, RDF.type, rdf_type]).each_subject do |subject| 
    g = RDF::Graph.new 
    rdf.query([subject, nil, nil]) do |s,p,o| 
    g << [s,p,o] 
    g << rdf_expand_blank_nodes(o) if o.node? 
    end 
end 

def rdf_expand_blank_nodes(object) 
    g = RDF::Graph.new 
    if object.node? 
    rdf.query([object, nil, nil]) do |s,p,o| 
     g << [s,p,o] 
     g << rdf_expand_blank_nodes(o) if o.node? 
    end 
    end 
    g 
end 
関連する問題