Java 如何获取Jena查询的所有主题?

Java 如何获取Jena查询的所有主题?,java,sparql,semantic-web,jena,Java,Sparql,Semantic Web,Jena,假设我有一些jena查询对象: String query = "SELECT * WHERE{ ?s <some_uri> ?o ...etc. }"; Query q = QueryFactory.create(query, Syntax.syntaxARQ); String query=“选择*WHERE{s?o…etc.}”; queryq=QueryFactory.create(Query,Syntax.syntaxARQ); 获取查询中三元组的所有主题的最佳方法是什么?

假设我有一些jena查询对象:

String query = "SELECT * WHERE{ ?s <some_uri> ?o ...etc. }";
Query q = QueryFactory.create(query, Syntax.syntaxARQ);
String query=“选择*WHERE{s?o…etc.}”;
queryq=QueryFactory.create(Query,Syntax.syntaxARQ);
获取查询中三元组的所有主题的最佳方法是什么?最好不必手动执行任何字符串解析/操作

例如,给定一个查询

SELECT * WHERE {
    ?s ?p ?o;
       ?p2 ?o2.
    ?s2 ?p3 ?o3.
    ?s3 ?p4 ?o4.
    <http://example.com> ?p5 ?o5.
}
选择*WHERE{
?s?p?o;
?p2?o2。
?s2?p3?o3。
?s3?p4?o4。
?p5?o5。
}
我希望能返回一些列表,看起来像

[?s, ?s2, ?s3, <http://example.com>]
[?s,?s2,?s3,]
换句话说,我想要查询中所有主题的列表。即使只有那些变量或文本/URI的主题也很有用,但我想在查询中找到所有主题的列表

我知道有一些方法可以返回结果变量(
Query.getResultVars
)和一些其他信息(请参阅),但我似乎找不到任何能够具体获取查询主题的方法(所有结果变量的列表也会返回谓词和对象)


感谢您的帮助。

有意思的问题。您需要做的是遍历查询,对于每个三元组块,遍历并查看第一部分

最健壮的方法是通过一个元素遍历器,它将遍历查询的每个部分。在您的情况下,这似乎有些过头了,但查询可以包含各种内容,包括
过滤器
选项
,以及嵌套的
选择
。使用助行器意味着你可以忽略那些东西,只关注你想要的东西:

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());
            }
        }
    }
);
Query q=QueryFactory.create(Query);//SPARQL 1.1
//记住这篇文章中不同的主题
最终设置主题=新HashSet();
//这将遍历查询的所有部分
ElementWalker.walk(q.getQueryPattern(),
//对于每个元素。。。
新元素visitorbase(){
//…当它是一块三元组时。。。
公共无效访问(ElementPathBlock el){
//…经历所有的三重考验。。。
迭代器三元组=el.patternElts();
while(triples.hasNext()){
//…抓住主题
subjects.add(triples.next().getSubject());
}
}
}
);

可能太晚了,但另一种方法是利用Jena ARQ库并创建给定查询的代数。一旦创建了代数,就可以编译它,并且可以遍历所有三元组(在where子句中给出)。下面是代码,我希望它有帮助:

Query query = qExec.getQuery(); //qExec is an object of QueryExecutionFactory

// Generate algebra of the query
Op op = Algebra.compile(query);
CustomOpVisitorBase opVisitorBase = new CustomOpVisitorBase();
opVisitorBase.opVisitorWalker(op);
List<Triple> queryTriples = opVisitorBase.triples;
Query Query=qExec.getQuery()//qExec是QueryExecutionFactory的一个对象
//生成查询的代数
Op=代数.编译(查询);
CustomOpVisitorBase opVisitorBase=新CustomOpVisitorBase();
opVisitorBase.opVisitorWalker(op);
List queryTriples=opVisitorBase.triples;
CustomOpVisitor类如下所示:

public class CustomOpVisitorBase extends OpVisitorBase {
List<Triple> triples = null;
void opVisitorWalker(Op op) {
    OpWalker.walk(op, this);
}

@Override
public void visit(final OpBGP opBGP) {
    triples = opBGP.getPattern().getList();
}
}
公共类CustomOpVisitorBase扩展了OpVisitorBase{
列表三元组=空;
void opVisitorWalker(Op){
奥普沃克。沃克(奥普,本);
}
@凌驾
公共无效访问(最终OpBGP OpBGP){
三元组=opBGP.getPattern().getList();
}
}

遍历三元组列表并使用给定的属性函数,如triple.getSubject()等。

查询字符串是给定的还是可以更改?因为你的问题可以很容易地通过改变查询来解决。我想我终于明白你的意思了。您不希望结果中包含所有主题,但希望查询中包含主题的所有绑定变量,对吗?如果是这样的话,请在问题中让它更明显。为什么不在结果变量上运行呢?是否要创建包含结果变量的表?如果没有,请举个例子。另外,我认为你的例子有错误。为清晰起见,您的预期结果不应该进行编辑吗。查询字符串已给定,无法更改。我希望获得查询中主题的所有绑定变量,以及作为查询中主题的任何文本/URI。因此,这从直觉上讲是有意义的,感谢您指出
ElementWalker
ElementVisitor
s。但是,这个实现似乎无法处理上述查询(或任何其他查询)。我发现调试这种visit方法的重写很困难;知道有什么问题吗?每当我尝试这种覆盖时,都会返回一个空列表。有人有其他的例子吗?您需要在ElementPathBlock中查找SPARQL 1.1以及ElementTriplesBlock。请看PatternVarsVisitor的工作原理。作为将来的参考,我只是缺少了一些东西,或者这实际上是一种很难学会如何在这个级别上使用的东西?除了这里模糊的引用之外,我找不到任何关于如何实现这一点的示例代码或信息:而且它似乎没有很好的文档记录。也许我只是个傻瓜,你什么都没错过。首先,对于普通用户来说,这不是一个常见的需求,所以它不会经常出现(商店实现者倾向于在jena dev等上闲逛,并直接询问这一点)。其次,在SPARQL标准化和Andy改进ARQ时,代码库的这一部分一直是一个移动目标。