2013-03-04 6 views
8

Angenommen ich einige jena Abfrage Objekt haben:Wie bekomme ich alle Themen einer Jena Query?

String query = "SELECT * WHERE{ ?s <some_uri> ?o ...etc. }"; 
Query q = QueryFactory.create(query, Syntax.syntaxARQ); 

Was wäre der beste Weg sein, alle Themen der Tripel in der Abfrage zu bekommen? Vorzugsweise ohne manuell eine String-Analyse/-Manipulation durchführen zu müssen.

Zum Beispiel gegeben eine Abfrage

SELECT * WHERE { 
    ?s ?p ?o; 
     ?p2 ?o2. 
    ?s2 ?p3 ?o3. 
    ?s3 ?p4 ?o4. 
    <http://example.com> ?p5 ?o5. 
} 

Ich hoffe, würde eine Liste zurückgegeben zu haben, die

[?s, ?s2, ?s3, <http://example.com>] 

Mit anderen Worten: wie

aussieht, ich die Liste aller Fächer in einer Abfrage möge. Es wäre sogar nützlich, nur die Subjekte zu haben, die Variablen oder Literale/Uris sind, aber ich würde gerne eine Liste aller Themen in der Abfrage finden.

Ich weiß, es gibt Methoden, um die Ergebnisvariablen (Query.getResultVars) und einige andere Informationen (siehe http://jena.apache.org/documentation/javadoc/arq/com/hp/hpl/jena/query/Query.html) zurückgeben, aber ich kann nichts finden, die speziell die Themen der Abfrage erhalten (eine Liste aller Ergebnisse Variablen würden auch die Prädikate und Objekte zurückgeben).

Jede Hilfe wird geschätzt.

+0

Ist die Abfragezeichenfolge angegeben oder können Sie sie ändern? Weil Ihr Problem ganz einfach durch Ändern der Abfrage gelöst werden kann. – Sentry

+0

Ich glaube, ich habe endlich verstanden, was du meinst. Sie wollen nicht alle Themen im Ergebnis, sondern alle Bindungsvariablen für Themen in der Abfrage, oder? Wenn ja, mach es in der Frage deutlicher. – Sentry

+0

Warum nicht über Ergebnis vars? Möchten Sie eine Tabelle mit Ergebnisvariablen erstellen? wenn nicht, bitte geben Sie ein Beispiel. –

Antwort

9

Interessante Frage. Was Sie tun müssen, ist durch die Abfrage zu gehen, und für jeden Block von Tripeln durchlaufen und den ersten Teil betrachten.

Die robusteste Methode ist ein Element-Walker, der jeden Teil der Abfrage durchläuft. Es scheint in Ihrem Fall übertrieben, aber Abfragen können alle möglichen Dinge enthalten, einschließlich FILTERs, OPTIONALs und verschachtelt SELECTs. Die Verwendung des Rollators bedeutet, dass Sie dieses Zeug ignorieren und sich nur auf das konzentrieren können, was Sie wollen:

Query q = QueryFactory.create(query); // SPARQL 1.1 

// Remember distinct subjects in this 
final Set<Node> subjects = new HashSet<Node>(); 

// This will walk through all parts of the query 
ElementWalker.walk(q.getQueryPattern(), 
    // For each element... 
    new ElementVisitorBase() { 
     // ...when it's a block of triples... 
     public void visit(ElementPathBlock el) { 
      // ...go through all the triples... 
      Iterator<TriplePath> triples = el.patternElts(); 
      while (triples.hasNext()) { 
       // ...and grab the subject 
       subjects.add(triples.next().getSubject()); 
      } 
     } 
    } 
); 
+0

Das macht also intuitiv Sinn, danke für den Hinweis auf 'ElementWalker' und' ElementVisitor's. Diese Implementierung scheint jedoch bei der obigen Abfrage nicht zu funktionieren (und auch nicht bei anderen). Ich finde es schwierig, diese Art des Übersteuerns der Besuchsmethode zu debuggen; irgendeine Idee, was könnte das Problem sein? Jedes Mal, wenn ich diese Art von Override versuche, bekomme ich nur eine leere Liste zurück. Hat jemand ein anderes Beispiel dafür? –

+2

Sie müssen in ElementPathBlock für SPARQL 1.1 sowie ElementTriplesBlock suchen. Siehe PatternVarsVisitor – AndyS

+0

Ah, natürlich. Die korrigierte Version oben funktioniert für mich. – user205512