我有一堆使用Apache Jena querybuilder API(SelectBuilder
类)的代码。我试图在我现有的SPARQL查询中添加这样的术语:
(?a ?b ?c) :hasMagicProperty ?this .
我已经验证此查询在TopBraid中有效,但我无法弄清楚如何在Jena API中表示(?a, ?b, ?c)
。如何将此Vars列表转换为有效的Jena资源节点,我该怎么做?
我愿意探索备用SPARQL构建框架,如果它们对类型文字,IRI和过滤器以及此列表构造有强大的支持。我已经浏览了几个其他框架来构建SPARQL查询,但它们似乎都没有列表构造。
修改
我的查询构建代码(在Groovy中)看起来像这样:
def selectBuilder = new SelectBuilder()
selectBuilder.addPrefixes(...)
def thisVar = Var.alloc('this')
selectBuilder.addOptional(thisVar, 'rdf:type', ':MyEntity')
def aVar = Var.alloc('a')
def bVar = Var.alloc('b')
def cVar = Var.alloc('c')
List<Var> abc = [aVar, bVar, cVar]
//this doesn't work!!!
selectBuilder.addWhere(abc, ':hasMagicProperty', thisVar)
selectBuilder.addWhere(aVar, ':hasACode', 'code A')
selectBuilder.addWhere(bVar, ':hasBCode', 'code B')
selectBuilder.addWhere(cVar, ':hasCCode', 'code C')
def sparqlQuery = selectBuilder.buildString()
我花了几个小时试图与RDFList课程一起工作,但我还没弄明白。我会继续努力,看看我能不能理解它。在此期间,任何帮助将不胜感激。 :)
修改
以下是不成功尝试使用RDFList:
//this code does not work!
def varNode = NodeFactory.createVariable('a')
def model = ModelFactory.createDefaultModel()
def rdfNode = model.asRDFNode(varNode)
def rdfList = new RDFListImpl(model.createResource().asNode(), model)
//this line throws an exception!!
rdfList.add(rdfNode)
selectBuilder.addWhere(rdfList, ':hasMagicProperty', thisVar)
//com.hp.hpl.jena.shared.PropertyNotFoundException: http://www.w3.org/1999/02/22-rdf-syntax-ns#rest
答案 0 :(得分:1)
我写了queryBuilder,我不认为在它的当前状态下它会做你想要的。查询构建器基于(但尚未完全实现)w3c SPARQL 1.1建议: http://www.w3.org/TR/2013/REC-sparql11-query-20130321/#rQuery
但是,我认为您可以使用Jena QueryFactory
创建查询String queryString = "SELECT * WHERE { "+
" OPTIONAL { ?this a :MyEntity } ."+
" (?a ?b ?c) :hasMagicProperty ?result . "+
" ?a :hasACode 'code A' . "+
" ?b :hasACode 'code B' . "+
" ?c :hasACode 'code C' ."+
" }";
Query query = QueryFactory.create(queryString) ;
不幸的是,我认为这不是你真正想要的。请注意,?这不会绑定到任何其他语句,因此将生成:MyEntity
,?a
,?b
和所有?c
类型主题的叉积。 ?结果``绑定。
如果您可以使用QueryFactory创建查询,我可以确保QueryBuilder支持它。
<强>更新强> 我更新了QueryBuilder(下一个Snapshot应该包含更改)。您现在应该能够执行以下操作:
Var aVar = Var.alloc('a')
Var bVar = Var.alloc('b')
Var cVar = Var.alloc('c')
selectBuilder.addWhere(selectBuilder.list(aVar, bVar, cVar), ':hasMagicProperty', thisVar)
selectBuilder.addWhere(aVar, ':hasACode', 'code A')
selectBuilder.addWhere(bVar, ':hasBCode', 'code B')
selectBuilder.addWhere(cVar, ':hasCCode', 'code C')
如果您还可以在列表参数中添加标准文本版本的值,例如:
selectBuilder.list( "<a>", "?b", "'c'" )
答案 1 :(得分:1)
以下方法是一种解决方法,使用多个三元组递归构建RDF列表:
/*
* Jena querybuilder does not yet support RDF lists. See:
* http://www.w3.org/TR/2013/REC-sparql11-query-20130321/#collections
*/
private Node buildRdfCollection(SelectBuilder queryBuilder, List<?> itemList) {
if (itemList.isEmpty()) {
return RDF.nil.asNode()
}
def head = itemList.first()
def rest = buildRdfCollection(queryBuilder, itemList.subList(1, itemList.size()))
def listNode = NodeFactory.createAnon()
queryBuilder.addWhere(listNode, RDF.first, head)
queryBuilder.addWhere(listNode, RDF.rest, rest)
return listNode
}
...
def listNode = buildRdfCollection(queryBuilder, abc)
queryBuilder.addWhere(listNode, ':hasMagicProperty', thisVar)
生成的SPARQL代码如下所示:
_:b0 rdf:first ?c ;
rdf:rest rdf:nil .
_:b1 rdf:first ?b ;
rdf:rest _:b0 .
_:b2 rdf:first ?a ;
rdf:rest _:b1 ;
:hasMagicProperty ?this .
这是一个啰嗦的等同于:
(?a ?b ?c) :hasMagicProperty ?this .