如何在Java中构建SPARQL查询?

11
8个回答

7
你可以使用两种方法在Jena中以编程方式构建查询:语法或代数。在jena wiki中有一个introduction
使用代数,你可以做如下操作:
Op op;
BasicPattern pat = new BasicPattern();                 // Make a pattern
pat.add(pattern);                                      // Add our pattern match
op = new OpBGP(pat);                                   // Make a BGP from this pattern
op = OpFilter.filter(e, op);                           // Filter that pattern with our expression
op = new OpProject(op, Arrays.asList(Var.alloc("s"))); // Reduce to just ?s
Query q = OpAsQuery.asQuery(op);                       // Convert to a query
q.setQuerySelectType();                                // Make is a select query

(来自维基页面)

它不是CriteriaBuilder(也不打算成为它),但已经接近了一些。您使用OpJoin而不是AND,使用OpUnion当您想要OR等等。在我的经验中,痛点在于表达式:您可能希望从字符串中解析它们。


7
最近的Jena版本添加了类似于StringBuilder的API,用于构建查询/更新字符串,并在需要时进行参数化。
该类称为ParameterizedSparqlString,以下是使用它创建查询的示例:
ParameterizedSparqlString queryStr = new ParameterizedSparqlString();
queryStr.setNSPrefix("sw", "http://skunkworks.example.com/redacted#");
queryStr.append("SELECT ?a ?b ?c ?d");
queryStr.append("{");
queryStr.append("   ?rawHit sw:key");
queryStr.appendNode(someKey);
queryStr.append(".");
queryStr.append("  ?rawHit sw:a ?a .");
queryStr.append("  ?rawHit sw:b ?b .");
queryStr.append("  ?rawHit sw:c ?c . ");
queryStr.append("  ?rawHit sw:d ?d .");
queryStr.append("} ORDER BY DESC(d)");

Query q = queryStr.asQuery();

免责声明 - 我是为Jena贡献此功能的开发者

请参见如何在各种API中对SPARQL查询进行参数化?以获取更多讨论。


4

我实现了SPARQL Java - 一种在Java中编写SPARQL查询的DSL。

它解决了IDE自动格式化连接的SPARQL查询字符串等问题。

例如:

String shortQuery = Q.prefix("books", "http://example.org/books#")
            .select("?book ?authorName", new where() {
                {
                    $("?book books:author ?author");
                    $("?author books:authorName ?authorName");
                }
            }).get();

3

我最近开始使用Sesame查询构建器。它看起来很有前途,但是它并没有提供太多的文档,让我很难找到例子。这里是一个简单的示例,可能会帮助你入门:

ParsedTupleQuery query = QueryBuilderFactory
            .select("pubProperty", "pubPropertyValue")
                .group()
                    .atom(cmResource(resourceId), LinkPublicationsTransformation.REFERENCE_URI, "pubUri")
                    .atom("pubUri", "pubProperty", "pubPropertyValue")
                    .filter(isLiteral("pubPropertyValue"))
                .closeGroup()
            .query();

请注意,isLiteralcmResource是我自己编写的小型静态辅助类。例如,isLiteral代表new IsLiteral(new Var("...")),后者使用我的常用前缀创建URI。

你可能还会对SPARQLQueryRenderer感兴趣,它可以将ParsedQuery转换为String,以便进一步使用。

如果你最终采用了String(Builder)方法,我不建议这样做,请至少查看来自sesame-queryrenderedRenderUtils,其中包含所有方便添加< >围绕URI,转义特殊字符等的方法。


这个答案有点过时了:这个 QueryBuilder 现在已经过时了,被 RDF4J SparqlBuilder 取代了 - 请参见 https://dev59.com/yGw05IYBdhLWcg3wahNN#7303298。 - Jeen Broekstra

2

Eclipse RDF4J框架(Sesame的后继者)提供了一个存储库API,类似于JDBC-它允许您创建一个准备好的查询对象,并在执行之前注入变量绑定:

String query = "SELECT * WHERE {?X ?P ?Y }";
TupleQuery preparedQuery = conn.prepareQuery(QuerLanguage.SPARQL, query);
preparedQuery.setBinding("X", someValue);
...
TupleQueryResult result = preparedQuery.evaluate();

此外,RDF4J拥有一个SparqlBuilder(最初称为spanqit)- 一种用于SPARQL的Java DSL,允许您像以下代码一样在代码中创建SPARQL查询:(链接)
query.prefix(foaf).select(name)
    .where(x.has(foaf.iri("name"), name))
    .orderBy(name)
    .limit(5)
    .offset(10);

1
我刚发布了一个名为Spanqit的beta项目,用于实现这一目标。
我努力追求可读性和直观的界面。例如,以下是创建查询的一些示例Spanqit语法:
query.prefix(foaf).select(name)
    .where(x.has(foaf.iri("name"), name))
    .orderBy(name)
    .limit(5)
    .offset(10);

检查一下,随时评论并提出改进意见!

有什么进展吗?我很想听听反馈! - anqit
到目前为止还没有,但是谢谢提醒。我会尽快测试它。 - Martin Schlagnitweit
1
该项目已被Eclipse基金会的RDF4J项目采用,可以在此处查看文档:http://docs.rdf4j.org/sparqlbuilder/。 - anqit

1

0

但是我想要避免链接问题中使用的语法。 - Martin Schlagnitweit
好的。我误解了你的问题。我找到了其他链接,谈论了一个名为“Empire”的库,它是一个类似于JPA的接口,使用SPARQL作为底层(http://weblog.clarkparsia.com/2010/01/11/empire-05/),但我没有在github上找到源代码。 - Guido
我终于在https://github.com/mhgrove/Empire找到了它,但我以前从未使用过。希望它能满足你的需求,尽管似乎很难开始使用它:http://weblog.clarkparsia.com/2010/05/07/rdf-for-fun-and-profit-using-empire - Guido

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接