简体   繁体   English

保存并重用SPARQL查询的结果

[英]Saving and reusing the result of a SPARQL query

I am using Jena to query an owl file through Eclipse. 我正在使用Jena通过Eclipse查询owl文件。 I want to do some successive queries and every new query will use the results of the previous query. 我想做一些连续的查询,每个新查询都将使用前一个查询的结果。 I want to do it in different ?SELECT and save every time the result of a query in order to use it again in a new query. 我想用不同的方法做什么?每次查询结果时选择并保存,以便在新查询中再次使用它。 I dont want to insert the values of the variables by myself but automatically occur from the queries. 我不想自己插入变量的值,但自动从查询中发生。 Any ideas whats a suitable way to achieve this? 任何想法是否有适当的方法来实现这一目标? Thanks in advance 提前致谢

I think that there are two primary options here: 我认为这里有两个主要选择:

  1. a . a if you're interested in just one QuerySolution from a ResultSet and you're running these queries locally, then you can take the QuerySolution and use it as an initialBindings argument for the QueryExecution, and the values of the variables in the QuerySolution will be used in the second query. 如果您只对ResultSet中的一个QuerySolution感兴趣并且您在本地运行这些查询,则可以使用QuerySolution并将其用作initialBindings参数,并使用initialBindings中的变量值在第二个查询中。 This probably only works for local queries (since some the values in the ResultSet could be blank nodes whose values wouldn't make sense in a remote context), and it's only useful if you have a single QuerySolution of interest. 这可能仅适用于本地查询(因为ResultSet中的某些值可能是空值节点,其值在远程上下文中没有意义),并且仅在您感兴趣的单个QuerySolution时才有用。
  1. b . b The single QuerySolution could also be used to set some values in a ParameterizedSparqlString. 单个QuerySolution还可用于在ParameterizedSparqlString中设置一些值。 In this case, the values are substituted in before you create the actual Query or QueryExecution object, and you could do some other manipulation if you needed as well. 在这种情况下,在创建实际的Query或QueryExecution对象之前替换值,如果需要,还可以执行其他操作。 You might not be able to reliably run remote queries if some of the results are blank nodes, but you will be able to use this approach with remote endpoints, which you can't do with the initialBindings approach. 你可能不能够可靠地运行远程查询,如果一些结果是空白的节点,但您能够使用远程终端,你不能用做这种做法initialBindings方法。

  2. The more general solution uses SPARQL 1.1's VALUES to provide the content of the ResultSet in a VALUES block. 更通用的解决方案使用SPARQL 1.1的VALUES在VALUES块中提供ResultSet的内容。 This is more portable, because any endpoint should be able to handle the VALUES block, and it's more general, because it can handle a bunch of bindings, not just one. 这更具可移植性,因为任何端点都应该能够处理VALUES块,并且它更通用,因为它可以处理一堆绑定,而不仅仅是一个绑定。

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import com.hp.hpl.jena.query.ParameterizedSparqlString;
import com.hp.hpl.jena.query.QueryExecution;
import com.hp.hpl.jena.query.QueryExecutionFactory;
import com.hp.hpl.jena.query.QuerySolution;
import com.hp.hpl.jena.query.QuerySolutionMap;
import com.hp.hpl.jena.query.ResultSet;
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.sparql.core.Var;
import com.hp.hpl.jena.sparql.engine.binding.Binding;


public class ReuseResults {

    final static String turtleContent = "" +
            "@prefix : <http://example.org/> .\n" +
            "\n" +
            ":alice :hasName \"Alice\" .\n" +
            ":alice :hasAddress \"4222 Clinton Way\" .\n" +
            ":herman :hasName \"Herman\".\n" +
            ":herman :hasAddress \"1313 Mockingbird Lane\" .\n" +
            ":DrWho :hasAddress \"The TARDIS\"" + 
            "";

    // Read the model from the turtle content
    final static Model model = ModelFactory.createDefaultModel() 
            .read( new ByteArrayInputStream( turtleContent.getBytes()), null, "TURTLE" );

    final static String findAlice = "" +
            "prefix : <http://example.org/>\n" +
            "select ?alice where {\n" +
            "  ?alice :hasName \"Alice\" .\n" +
            "}\n" +
            "";

    final static String findAliceAddress = "" +
            "prefix : <http://example.org/>\n" +
            "select ?address where {\n" +
            "  ?alice :hasAddress ?address .\n" +
            "}\n" +
            "";

    public static void useInitialBindingsFromQuerySolution() throws IOException {
        System.out.println( "== useInitialBindingsFromQuerySolution ==" );
        // execute the query that finds a binding for ?alice.  There should be just one 
        // query solution in the result set.
        final ResultSet aliceResults = QueryExecutionFactory.create( findAlice, model ).execSelect();
        final QuerySolution solution = aliceResults.next();
        // Use the single query solution from the result set as initial bindings for
        // the second query (which uses the variable ?alice).
        final ResultSet addressResults = QueryExecutionFactory.create( findAliceAddress, model, solution ).execSelect();
        ResultSetFormatter.out( addressResults );
    }

    public static void useParameterizedSPARQLString() {
        System.out.println( "== useParameterizedSPARQLString ==" );
        // execute the query that finds a (single) binding for ?alice.  Then create
        // a query solution map containing those results.
        final ResultSet aliceResults = QueryExecutionFactory.create( findAlice, model ).execSelect();
        final QuerySolutionMap map = new QuerySolutionMap();
        map.addAll( aliceResults.next() );
        // Create a ParameterizedSparqlString from the findAliceAddress query string (if this
        // approach were taken, findAliceAddress could actually *be* a Param.SparqlString, of
        // course).
        final ParameterizedSparqlString pss = new ParameterizedSparqlString( findAliceAddress );
        System.out.println( pss.toString() );
        pss.setParams( map );
        System.out.println( pss.toString() );
        // execute the query and show the results
        ResultSetFormatter.out( QueryExecutionFactory.create( pss.toString(), model ).execSelect() );
    }

    final static String findNamed = "" +
            "prefix : <http://example.org/>\n" +
            "select ?person where {\n" +
            "  ?person :hasName [] .\n" +
            "}\n" +
            "";

    final static String findPersonAddress = "" +
            "prefix : <http://example.org/>\n" +
            "select ?address where { " +
            "  ?person :hasAddress ?address .\n" +
            "}\n" +
            "";

    public static void useValuesFromResultSet() { 
        System.out.println( "\n== useValuesFromResultSet ==" );
        final ResultSet namedResults = QueryExecutionFactory.create( findNamed, model ).execSelect();
        final QueryExecution qe = QueryExecutionFactory.create( findPersonAddress, model );
        System.out.println( "=== Query Before Adding VALUES ===\n" + qe.getQuery() );
        // Create a list of the variables from the result set
        List<Var> variables = new ArrayList<>();
        for ( final String varName : namedResults.getResultVars() ) {
            variables.add( Var.alloc( varName ));
        }
        // Create a list of the bindings from the result set.
        List<Binding> values = new ArrayList<>();
        while ( namedResults.hasNext() ) {
            values.add( namedResults.nextBinding() );
        }
        // add a values block to the query
        qe.getQuery().setValuesDataBlock(variables, values);
        System.out.println( "\n=== Query After Adding VALUES ===\n" + qe.getQuery() );
        ResultSetFormatter.out( qe.execSelect() );
    }

    public static void main(String[] args) throws IOException {
        useInitialBindingsFromQuerySolution(); // 1.a.
        useParameterizedSPARQLString();        // 1.b.
        useValuesFromResultSet();              // 2.
    }
}

Here's the output that's generated. 这是生成的输出。 In the first case, the fact that Alice's address gets selected shows that the value of ?alice carried from the first ResultSet to the initialBindings . 在第一种情况下,Alice的地址被选中的事实表明,从第一个ResultSet到initialBindings?alice的值。 In the second case, I've printed the query before and after adding the VALUES clause so that the difference is clear. 在第二种情况下,我在添加VALUES子句之前和之后打印了查询,以便区分清楚。 Note that this will work even if the ResultSet binds multiple variables. 请注意,即使ResultSet绑定多个变量,这也会起作用。 The syntax in the case of multiple variables would be VALUES (?v1 ... ?vN) { (value11 ... value1N) ... (valueM1 ... valueMN) } . 多个变量的语法是VALUES (?v1 ... ?vN) { (value11 ... value1N) ... (valueM1 ... valueMN) }

== useInitialBindingsFromQuerySolution ==
----------------------
| address            |
======================
| "4222 Clinton Way" |
----------------------

== useParameterizedSPARQLString ==
prefix : <http://example.org/>
select ?address where {
  ?alice :hasAddress ?address .
}

prefix : <http://example.org/>
select ?address where {
  <http://example.org/alice> :hasAddress ?address .
}

----------------------
| address            |
======================
| "4222 Clinton Way" |
----------------------

== useValuesFromResultSet ==
=== Query Before Adding VALUES ===
PREFIX  :     <http://example.org/>
SELECT  ?address
WHERE
  { ?person :hasAddress ?address }

=== Query After Adding VALUES ===
PREFIX  :     <http://example.org/>
SELECT  ?address
WHERE
  { ?person :hasAddress ?address }
VALUES ?person { :herman :alice }

---------------------------
| address                 |
===========================
| "1313 Mockingbird Lane" |
| "4222 Clinton Way"      |
---------------------------
  1. As I know,there is cascade query in SPARQL like SQL. 据我所知,SPARQL中有级联查询,如SQL。
  2. stored the result in file,and match it in sparql query. 将结果存储在文件中,并在sparql查询中匹配它。

may work for you. 可能适合你。

refer: http://www.w3.org/TR/sparql11-query/ 参考: http//www.w3.org/TR/sparql11-query/

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM