SPARQL 教程六

模式中的备选方案(Alternatives in a Pattern)

在处理半结构化数据时,另一种方法是查询可能性中的其中一种。本节将介绍 UNION 模式,即从多种可能性中选择一种进行查询。

  在使用 UNION 关键字时,如果两个子模式都匹配,并且它们的结果有重叠,那么查询结果中可能会包含重复的值。就是说不管两个子模式的变量是否相同,都会输出两个值。

使用 UNION 操作符来实现获取相同数据的两种方式。

  vCard词汇表和FOAF词汇表都有用于表示人名的属性。在vCard中,这个属性是vCard:FN,它代表“格式化名称”;而在FOAF中,这个属性是foaf:name。在本节中,我们将查看一小部分数据,其中的人名可以用 FOAF 或 vCard 词汇表给出。

  假设我们有 一个 RDF 图 ,其中包含使用 vCard 和 FOAF 词汇表的姓名信息。下面的两部分是 RDF 文件的 Turtle 格式。

1、如果一个节点具有两个属性,属性间用 “;” 隔开。

@prefix foaf: <http://xmlns.com/foaf/0.1/> .
@prefix vcard: <http://www.w3.org/2001/vcard-rdf/3.0#> .

_:a a foaf:Person ;
    foaf:name   "Matt Jones" .

_:b a foaf:Person ;
    foaf:name   "Sarah Jones";
    vcard:FN    "Sarah Jones11111" .
_:c a foaf:Person ;
    vcard:FN    "Becky Smith" .

_:d a foaf:Person ;
    vcard:FN    "John Smith" .

2、如果一个节点具有两个属性,属性间用 “,” 隔开。

@prefix foaf:       <http://xmlns.com/foaf/0.1/> .
@prefix vcard:      <http://www.w3.org/2001/vcard-rdf/3.0#> .


_:a foaf:name   "Matt Jones",  "2313521" .

_:b foaf:name   "Sarah Jones" .

_:c vcard:FN    "Becky Smith" .

_:d vcard:FN    "John Smith" .

  [] 是一个空白节点(匿名资源)的缩写。它表示一个不具体的资源,相当于占位符。在这个模式中,它表示我们不关心这个资源是什么,只要它有 foaf:name 属性即可。当名称信息可以是两种形式时,访问名称信息的查询可以是 (q-union1.rq):

PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX vCard: <http://www.w3.org/2001/vcard-rdf/3.0#>

SELECT ?name
WHERE
{
   { [] foaf:name ?name } UNION { [] vCard:FN ?name }
}

这将返回以下结果:

-----------------
| name          |
=================
| "Matt Jones"  |
| "Sarah Jones" |
|"Sarah Jones02"|
| "Becky Smith" |
| "John Smith"  |
-----------------

Java 代码如下:

import org.apache.jena.query.Query;
import org.apache.jena.query.QueryExecution;
import org.apache.jena.query.QueryExecutionFactory;
import org.apache.jena.query.QueryFactory;
import org.apache.jena.query.QuerySolution;
import org.apache.jena.query.ResultSet;
import org.apache.jena.rdf.model.Model;
import org.apache.jena.rdf.model.ModelFactory;
import org.apache.jena.riot.Lang;
import org.apache.jena.riot.RDFDataMgr;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;

public class Union01 {
    static final String inputFileName  = "java01/src/main/java/come/jena/rdf/test02.ttl";
    public static void main(String[] args) {
        // Load RDF data into a model
        Model model = ModelFactory.createDefaultModel();
        InputStream inputStream = null;
        try {
            inputStream = new FileInputStream(inputFileName);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        RDFDataMgr.read(model, inputStream, Lang.TURTLE);
        // Define a SPARQL query
        String queryString =  "PREFIX pr:<http://www.w3.org/2001/vcard-rdf/3.0#>\n" +
                "PREFIX foaf: <http://xmlns.com/foaf/0.1/>\n" +
                "SELECT ?name " +
                "WHERE {   { [] foaf:name ?name } UNION { [] pr:FN ?name  }}";
        Query query = QueryFactory.create(queryString);
        // Execute the query
        try (QueryExecution qexec = QueryExecutionFactory.create(query, model)) {
            ResultSet results = qexec.execSelect();
            // Process the query results
            while (results.hasNext()) {
                QuerySolution soln = results.nextSolution();
                //System.out.println(soln);
                //System.out.println( soln);
                System.out.println("name: " + soln.get("?name"));
            }
        }
        catch (Exception e){
            e.printStackTrace();
        }
    }
}

运行结果:

在这里插入图片描述

  名称使用哪种表达式并不重要,重要的是设置名称变量。正如本查询(q-union-1alt.rq)所示,使用 FILTER 可以实现这一目的,这两种查询的结果一样:

PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX vCard: <http://www.w3.org/2001/vcard-rdf/3.0#>

SELECT ?name
WHERE
{
  [] ?p ?name
  FILTER ( ?p = foaf:name || ?p = vCard:FN )
}

Java 代码如下:

import org.apache.jena.query.Query;
import org.apache.jena.query.QueryExecution;
import org.apache.jena.query.QueryExecutionFactory;
import org.apache.jena.query.QueryFactory;
import org.apache.jena.query.QuerySolution;
import org.apache.jena.query.ResultSet;
import org.apache.jena.rdf.model.Model;
import org.apache.jena.rdf.model.ModelFactory;
import org.apache.jena.riot.Lang;
import org.apache.jena.riot.RDFDataMgr;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;

public class Union01 {
    static final String inputFileName  = "java01/src/main/java/come/jena/rdf/test02.ttl";
    public static void main(String[] args) {
        // Load RDF data into a model
        Model model = ModelFactory.createDefaultModel();
        InputStream inputStream = null;
        try {
            inputStream = new FileInputStream(inputFileName);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        RDFDataMgr.read(model, inputStream, Lang.TURTLE);
        // Define a SPARQL query
        String queryString =  "PREFIX pr:<http://www.w3.org/2001/vcard-rdf/3.0#>\n" +
                "PREFIX foaf: <http://xmlns.com/foaf/0.1/>\n" +
                "SELECT  ?name " +
                "WHERE {   []  ?p  ?name . " +
                " FILTER (?p = foaf:name || ?p = pr:FN)  }";
        Query query = QueryFactory.create(queryString);
        // Execute the query
        try (QueryExecution qexec = QueryExecutionFactory.create(query, model)) {
            ResultSet results = qexec.execSelect();
            // Process the query results
            while (results.hasNext()) {
                QuerySolution soln = results.nextSolution();
                System.out.println("name: " + soln.get("?name"));
            }
        }
        catch (Exception e){
            e.printStackTrace();
        }
    }
}

运行结果:

在这里插入图片描述

  测试属性是一个 URI 还是另一个 URI。解决方案的顺序可能不尽相同。 第一种形式更有可能更快,这取决于所使用的数据和存储,因为第二种形式可能需要从图中获取所有三元组,以匹配每个未绑定变量(或空白节点)的三元组模式,然后测试每个 ?p 是否与其中一个值相匹配。这将取决于查询优化器的复杂程度,即它是否发现可以更有效地执行查询,并能将约束向下传递以及传递到存储层。

UNION-记住数据是在哪里找到的。

  上面的例子在每个分支中使用了相同的变量。如果使用不同的变量,则应用程序可以发现导致匹配的子模式(q-union2.rq):

PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX vCard: <http://www.w3.org/2001/vcard-rdf/3.0#>

SELECT ?name1 ?name2
WHERE
{
   { [] foaf:name ?name1 } UNION { [] vCard:FN ?name2 }
}

查询结果:

---------------------------------
| name1         | name2         |
=================================
| "Matt Jones"  |               |
| "Sarah Jones" |               |
|"Sarah Jones02"|               |
|               | "Becky Smith" |
|               | "John Smith"  |
---------------------------------

Java 代码如下:

import org.apache.jena.query.Query;
import org.apache.jena.query.QueryExecution;
import org.apache.jena.query.QueryExecutionFactory;
import org.apache.jena.query.QueryFactory;
import org.apache.jena.query.QuerySolution;
import org.apache.jena.query.ResultSet;
import org.apache.jena.rdf.model.Model;
import org.apache.jena.rdf.model.ModelFactory;
import org.apache.jena.riot.Lang;
import org.apache.jena.riot.RDFDataMgr;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;

public class Union01 {
    static final String inputFileName  = "java01/src/main/java/come/jena/rdf/test02.ttl";
    public static void main(String[] args) {
        // Load RDF data into a model
        Model model = ModelFactory.createDefaultModel();
        //model.read(inputFileName); // Load your RDF data file

        InputStream inputStream = null;
        try {
            inputStream = new FileInputStream(inputFileName);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        RDFDataMgr.read(model, inputStream, Lang.TURTLE);

        // Define a SPARQL query
        String queryString =  "PREFIX pr:<http://www.w3.org/2001/vcard-rdf/3.0#>\n" +
                "PREFIX foaf: <http://xmlns.com/foaf/0.1/>\n" +
                "SELECT  ?name1  ?name2 " +
                "WHERE {   { [] foaf:name ?name1 } UNION { [] pr:FN ?name2 }  }";
        Query query = QueryFactory.create(queryString);
        // Execute the query
        try (QueryExecution qexec = QueryExecutionFactory.create(query, model)) {
            ResultSet results = qexec.execSelect();
            // Process the query results
            while (results.hasNext()) {
                QuerySolution soln = results.nextSolution();
                System.out.print("name1: " + soln.get("name1"));
                System.out.println("                 name2: " + soln.get("name2"));
            }
        }
        catch (Exception e){
            e.printStackTrace();
        }
    }
}

运行结果:

在这里插入图片描述

  第二个查询通过将姓名分配给不同的变量,保留了姓名来源的信息。

OPTIONAL and UNION

  在实际应用中,OPTIONAL 比 UNION 更常用,但两者都有各自的用途。OPTIONAL 用于扩充找到的解决方案,而 UNION 则用于连接两种可能性的解决方案。它们不一定以相同的方式返回信息:
查询(q-union3.rq):

PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX vCard: <http://www.w3.org/2001/vcard-rdf/3.0#>

SELECT ?name1 ?name2
WHERE
{
  ?x a foaf:Person
  OPTIONAL { ?x  foaf:name  ?name1 }
  OPTIONAL { ?x  vCard:FN   ?name2 }
}

查询结果:

---------------------------------
| name1         | name2         |
=================================
| "Matt Jones"  |               |
| "Sarah Jones" |               |
|"Sarah Jones02"|               |
|               | "Becky Smith" |
|               | "John Smith"  |
---------------------------------

  但要注意在每个 OPTIONAL 中使用 ?name,因为这是一个取决于顺序的查询。

Jena 官方文档:https://jena.apache.org/tutorials/sparql_union.html

下一篇:命名图

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值