1

我正在尝试根据给定查询构建一个新查询(旧查询——我无法更改)。

假设我得到一个简单有效的 SPARQL 查询,SELECT ?s WHERE{ ?s ?p ?o }. 假设我制作了上述查询的耶拿查询对象,并将查询模式作为 Java 中的 ElementGroup 获取,如下所示:

Query q = QueryFactory.create("SELECT ?s WHERE{ ?s ?p ?o }, Syntax.syntaxSPARQL_11);
ElementGroup oldQP = (ElementGroup)q.getQueryPattern();

我之前向旧查询模式添加新三元组的方式是使用以下语法:

Triple t = Triple.create(...);
oldQP.addTriplePattern(t);

但是,当您创建新的查询对象时:

Query nq = q.cloneQuery();
nq.setQueryPattern(oldQP);
nq.setQuerySelectType();
nq.setQueryResultStar(false);
nq.addResultVar("s");

你最终得到一个看起来像的查询

SELECT ?s WHERE{
    ?s ?p ?o
    ?s2 ?p2 ?s.
}

因为当您设置对象的 QueryPattern 时,它不会识别/关心第一个三元组不会以句点结尾。这会在查询运行时导致解析错误...

Encountered " <VAR1> "?s2 "" at line 10, column 3.
Was expecting one of:
"graph" ...
"optional" ...
"minus" ...
"bind" ...
"service" ...
"let" ...
"exists" ...
"not" ...
"filter" ...
"{" ...
"}" ...
";" ...
"," ...
"." ...

因为这显然不是有效的 SPARQL。那么,如何避免这个问题呢?如果所有三元组都有关闭期,则不会出现此问题,但我似乎找不到任何方法来完成这项工作。

谢谢!

4

3 回答 3

1

我不确定我是否完全遵循您的问题

第二个查询来自哪里?您是否正在调用toString()新的查询对象,在这种情况下,这可能是打印查询的内部逻辑中的错误。

另外,您使用的是什么版本的 ARQ?

于 2013-03-22T18:35:13.107 回答
1

所以我似乎找到了一种解决方法/解决方案。在调试并更仔细地查看ElementGroup该行创建的对象之后

ElementGroup oldQP = (ElementGroup)q.getQueryPattern();

我注意到它包含一个 Element 对象的 ArrayList(通过 method 检索ElementGroup.getElements())。在我尝试添加三元组(通过ElementGroup.addTriplePattern(...)方法)之前,这个列表中唯一的东西是 Type 的对象ElementPathBlock。好的,酷。

接下来,我尝试通过上述方法添加三元组,如下所示:

Triple t = Triple.create(...);
oldQP.addTriplePattern(t);

我注意到这ElementTriplesBlock为 ElementGroup 的元素列表添加了一个新元素。看来这就是罪魁祸首。所以,我的解决方案是抓住最后一次出现的ElementPathBlock,并将三元组添加到该对象而不是将它们添加到 ElementGroup (从而避免将新的添加ElementTriplesBlock到 ArrayList ):

//same as before
Query q = QueryFactory.create("SELECT ?s WHERE{ ?s ?p ?o }, Syntax.syntaxSPARQL_11);
Query nq = q.cloneQuery();
ElementGroup oldQP = (ElementGroup)q.getQueryPattern();
Triple t = Triple.create(Var.alloc("s2"), Var.alloc("p2"), Var.alloc("s));

//new
ElementPathBlock epb;
int index = -1;
for(int i=0; i<oldQP.getElements().size(); i++){
    if(oldQP.getElements().get(i) instanceof ElementPathBlock){
        //...get last index of instanceof ElementPathBlock, if exists.
        index = i;
    }
}
if(index > -1){
    //...found occurence of ElementPathBlock we will add to
    epb = (ElementPathBlock) oldQP.getElements().get(index);
}else{
    //...no occurence, so make new ElementPathBlock to add
    epb = new ElementPathBlock();
}
//add Triple(s) to epb, not to oldQP
epb.addTriple(t);
//re-add (or add for first time) ElementPathBlock to the ArrayList of Elements
if(index > -1){
    oldQP.getElements().set(index, epb);
}else{
    oldQP.getElements().add(epb);
}

//same as before
nq.setQueryPattern(oldQP);
nq.setQuerySelectType();
nq.setQueryResultStar(false);
nq.addResultVar("s");

现在查看 oldQP,经过上述操作,我们看到它的格式正确,句号放置正确:

{?s ?p ?o.
 ?s2 ?p2 ?s.
}
于 2013-03-25T14:22:28.420 回答
0

下面的代码按照您的描述创建一个查询,复制它,添加一个三元组模式,打印它,然后运行这两个查询。您是对的,查询的打印形式缺少.通常会出现的位置。然而,正如 RobV指出的那样,打印异常对查询结果没有任何影响。如果您在实际案例中得到不同的结果,您能否强调它与此不同的地方?

import com.hp.hpl.jena.graph.Triple;
import com.hp.hpl.jena.query.Query;
import com.hp.hpl.jena.query.QueryExecutionFactory;
import com.hp.hpl.jena.query.QueryFactory;
import com.hp.hpl.jena.query.ResultSetFormatter;
import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.rdf.model.ModelFactory;
import com.hp.hpl.jena.rdf.model.Property;
import com.hp.hpl.jena.rdf.model.Resource;
import com.hp.hpl.jena.sparql.core.Var;
import com.hp.hpl.jena.sparql.syntax.ElementGroup;

public class AddTriplePattern {
    public static void main(String[] args) {
        // Create the original query
        final String queryString = "" +
                "select * where {\n" +
                "  ?s ?p ?o .\n" +
                "}\n" +
                "";
        final Query query = QueryFactory.create( queryString );

        // Create the new query and add `?s2 ?p2 ?o2`. Print the new query
        // before and after adding the triple pattern.  Sure enough, after 
        // the modification, the pattern is printed without a `.` between the 
        // triples.  The space between the variables is also a bit bigger.
        final Query newQuery = QueryFactory.create( query );
        System.out.println( "== before ==\n"+newQuery );
        final ElementGroup eg = (ElementGroup) newQuery.getQueryPattern();
        final Triple t = new Triple( Var.alloc( "s2"), Var.alloc( "p2" ), Var.alloc( "o2" ));
        eg.addTriplePattern( t );
        newQuery.setQueryResultStar(false);
        newQuery.addResultVar( "s2" );
        System.out.println( "== after ==\n"+newQuery );

        // Create a model with a single triple [a, a, a].
        final Model model = ModelFactory.createDefaultModel();
        final Resource a = model.createResource( "urn:ex:a" );
        model.add( a, a.as( Property.class ), a );

        // Run both the original query and the new query on the model.  Both
        // return the expected results.
        ResultSetFormatter.out( QueryExecutionFactory.create( query, model ).execSelect() );
        ResultSetFormatter.out( QueryExecutionFactory.create( newQuery, model ).execSelect() );
    }
}

输出是:

== before ==
SELECT  *
WHERE
  { ?s ?p ?o }

== after ==
SELECT  ?s2
WHERE
  { ?s ?p ?o
    ?s2  ?p2  ?o2 .
  }

----------------------------------------
| s          | p          | o          |
========================================
| <urn:ex:a> | <urn:ex:a> | <urn:ex:a> |
----------------------------------------
--------------
| s2         |
==============
| <urn:ex:a> |
--------------
于 2013-07-24T19:06:11.327 回答