0

我有一堆使用 Apache Jena querybuilder API(SelectBuilder类)的代码。我正在尝试将这样的术语添加到我现有的 SPARQL 查询中:

        (?a ?b ?c) :hasMagicProperty ?this .

我已验证此查询在 TopBraid 中有效,但我不知道如何(?a, ?b, ?c)在 Jena API 中表示。我需要做什么才能将此 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
4

2 回答 2

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 .
于 2015-10-28T15:44:11.520 回答
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) ;

不幸的是,我认为这不是你真正想要的。请注意,?this 不绑定到任何其他语句,因此将产生所有:MyEntity类型主题与?a?b?c`?result` 绑定的叉积。

如果您可以使用 QueryFactory 创建查询,我可以确保 QueryBuilder 将支持它。

更新 我已经更新了 QueryBuilder(下一个快照应该包含更改)。您现在应该能够执行以下操作:

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'" )
于 2015-10-27T23:19:48.103 回答