如何使用jena querybuilder构建SPARQL列表输入?

时间:2015-10-26 16:43:37

标签: java sparql jena apache-jena jena-querybuilder

我有一堆使用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

2 个答案:

答案 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 .