SPARQL Tutorial

前言

  本文是SPARQL官方入门教程,通过示例介绍SPARQL的主要功能。SPARQL是一种查询语言,用于查询RDF结构的数据。虽然RDF数据具备推理性,但是SPARQL本身没有推理查询功能,它是面向数据的,只能查询数据中包含的信息。
官方文档:sparql tutorial

1 JENA安装

  本教程演示在windows 10系统下安装JENA。JENA官方下载地址:https://jena.apache.org/download/index.cgi#, 选择.zip文件,下载后解压即可。安装JENA的前提是安装了Java运行环境。解压后设置JENA环境变量。
  在系统的环境变量中新建变量JENA_HOME,如下图所示,变量值填写你的JENA解压地址。
在这里插入图片描述
  然后在系统环境变量的“PATH”变量中添加值“;%JENA_HOME%\bat”。最后测试安装是否成功,在cmd终端中输入命令:sparql --version,将出现版本号信息:
在这里插入图片描述

2 Data Format

  首先我们要清楚待查询数据的结构。SPARQL是在RDF图上查询,一个RDF图就是一组三元组。在Jena数据库中将RDF图称为模型(models),将三元组称为陈述(statements)。有很多种协议用于描述RDF三元组,描述三元组的方式称为序列化(serialization)。用何种序列化方式并不重要,我们关心的是三元组本身内容。RDF\XML是一种序列化方式,但这种方式不适合人类阅读。我们采用另一种序列化方式:Turtle。本文使用的数据如下图所示,数据下载地址:vc-db-1.rdf,格式是RDF/XML。
在这里插入图片描述

  使用Turtle方式描述上述图,得到如下文件内容:

@prefix vCard:   <http://www.w3.org/2001/vcard-rdf/3.0#> .
@prefix rdf:     <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .

<http://somewhere/MattJones/>  vCard:FN   "Matt Jones" .
<http://somewhere/MattJones/>  vCard:N    _:b0 .
_:b0  vCard:Family "Jones" .
_:b0  vCard:Given  "Matthew" .

<http://somewhere/RebeccaSmith/> vCard:FN    "Becky Smith" .
<http://somewhere/RebeccaSmith/> vCard:N     _:b1 .
_:b1 vCard:Family "Smith" .
_:b1 vCard:Given  "Rebecca" .

<http://somewhere/JohnSmith/>    vCard:FN    "John Smith" .
<http://somewhere/JohnSmith/>    vCard:N     _:b2 .
_:b2 vCard:Family "Smith" .
_:b2 vCard:Given  "John"  .

<http://somewhere/SarahJones/>   vCard:FN    "Sarah Jones" .
<http://somewhere/SarahJones/>   vCard:N     _:b3 .
_:b3 vCard:Family  "Jones" .
_:b3 vCard:Given   "Sarah" .

  上述内容中行的顺序可以打乱,机器在读取数据时并不关心数据的位置,这样写只是为了方便人类阅读。下载上面的数据,保存到本地电脑中。
  本文在JENA安装目录下新建doc\Tutorial文件夹,将vc-db-1.rdf文件保存到该文件夹中。

3 A First SPARQL Query

  本小节介绍一个简单的查询例子,并展示Jena数据库是如何执行查询过程的。
  查询的数据就是7.2节展示的数据,查询语句如下:

SELECT ?x
WHERE { ?x  <http://www.w3.org/2001/vcard-rdf/3.0#FN>  "John Smith" }

  这个语句来自q1.rq。“?”表示这是个变量,“x”是变量名。“<>”中的是一个URI,描述了一个资源地址。双引号中的内容表示字面量(literal)。Where从句中描述了一个RDF三元组,其中主体是要查询的变量,谓语和客体已经给出具体的值。JENA按照谓语和客体区数据库中查找对应的三元组,然后返回找到的三元组的主体。
  将这个查询语句保存为文件q1.rq,并保存到本地的doc/Tutorial文件夹下,也就是和7.2节的数据文件vc-db-1.rdf放一起。如下所示:
在这里插入图片描述
  打开cmd终端,进入doc/Tutorial目录下,执行命令:

sparql --data=vc-db-1.rdf --query=q1.rq

  出现如下内容:
在这里插入图片描述
  图中的“x”对应查询语句中的“x”,下方的值就是返回的结果。Where从句中也可以只指定一个值,其他两个值都是变量,如下查询语句:

SELECT ?x ?fname
WHERE {?x  <http://www.w3.org/2001/vcard-rdf/3.0#FN>  ?fname}

  将上述语句保存为文件q-bp1.rq,放到doc/Tutorial目录下。在终端执行命令:

sparql --data=vc-db-1.rdf --query=q-bp1.rq

  返回查询结果如下图。
在这里插入图片描述

4 Basic Patterns

  一个基本的pattern就是一组三元组pattern,即在where从句中可以有多个三元组。多个三元组中变量名相同的变量需要匹配同一个实体。如下的查询语句中,两个三元组中的变量y表示的是同一个实体。

SELECT ?givenName
WHERE
  { ?y  <http://www.w3.org/2001/vcard-rdf/3.0#Family>  "Smith" .
    ?y  <http://www.w3.org/2001/vcard-rdf/3.0#Given>  ?givenName .
  }

  将上述查询语句保存为文件q-bq2.rq,放到doc/Tutorial目录下。在终端执行命令:

sparql --data=vc-db-1.rdf --query=q-bp2.rq

  返回查询结果如下图。
在这里插入图片描述
  SPARQL支持URI简写,可将上面的查询语句改为如下形式:

PREFIX vcard:      <http://www.w3.org/2001/vcard-rdf/3.0#>

SELECT ?givenName
WHERE
 { ?y vcard:Family "Smith" .
   ?y vcard:Given  ?givenName .
 }

  第一行表示用vcard代替http://www.w3.org/2001/vcard-rdf/3.0#。将上述查询语句保存为文件q-bq3.rq,放到doc/Tutorial目录下。在终端执行命令:sparql --data=vc-db-1.rdf --query=q-bp3.rq。
  同样也可以返回查询的中间节点,上述查询中的节点‘y’就是中间节点,只要在select从句中加上该变量名即可,如下所示:

PREFIX vcard:      <http://www.w3.org/2001/vcard-rdf/3.0#>

SELECT ?y ?givenName
WHERE
 { ?y vcard:Family "Smith" .
   ?y vcard:Given  ?givenName .
 }

  将上述查询语句保存为文件q-bq4.rq,放到doc/Tutorial目录下。在终端执行命令:

sparql --data=vc-db-1.rdf --query=q-bp4.rq

  返回查询结果如下图。
在这里插入图片描述
  返回的结果中‘y’具有不同的值,这是因为这个变量在数据中是个空白节点,针对空白节点,系统自动安排变量值。即使是同一个空白节点,系统打印的变量值也是不同的。

5 Filters

  本文讲解如何给返回结果加上限制条件。第一种是使用正则表达式对返回结果中的字符串作出限制。语法如下:

FILTER regex(?x, "pattern" [, "flags"])

  Pattern表示给出的正则表达式,flag是可选项。给出如下查询语句:

PREFIX vcard: <http://www.w3.org/2001/vcard-rdf/3.0#>

SELECT ?g
WHERE
{ ?y vcard:Given ?g .
  FILTER regex(?g, "r", "i") }

  “r”表示返回的字符串中需要包含字母“r”,“i”是一个flag,表示不区分字符串中的大小写。将上述查询语句保存为文件q-f1.rq,放到doc/Tutorial目录下。在终端执行命令:

sparql --data=vc-db-1.rdf --query=q-f1.rq

  返回查询结果如下图。
在这里插入图片描述
  第二种是按条件返回结果。我们使用新的数据集,在其中加入人物的年龄信息,部分内容如下所示:

<rdf:RDF
  xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#'
  xmlns:vCard='http://www.w3.org/2001/vcard-rdf/3.0#'
  xmlns:info='http://somewhere/peopleInfo#'
   >

  <rdf:Description rdf:about="http://somewhere/JohnSmith">
    <vCard:FN>John Smith</vCard:FN>
    <info:age rdf:datatype='http://www.w3.org/2001/XMLSchema#integer'>25</info:age>
    <vCard:N rdf:parseType="Resource">
	<vCard:Family>Smith</vCard:Family>
	<vCard:Given>John</vCard:Given>
    </vCard:N>
  </rdf:Description>

  <rdf:Description rdf:about="http://somewhere/RebeccaSmith">
    <vCard:FN>Becky Smith</vCard:FN>
    <info:age rdf:datatype='http://www.w3.org/2001/XMLSchema#integer'>23</info:age>
    <vCard:N rdf:parseType="Resource">
	<vCard:Family>Smith</vCard:Family>
	<vCard:Given>Rebecca</vCard:Given>
    </vCard:N>
  </rdf:Description>

  <rdf:Description rdf:about="http://somewhere/SarahJones">
    <vCard:FN>Sarah Jones</vCard:FN>
    <vCard:N rdf:parseType="Resource">
	<vCard:Family>Jones</vCard:Family>
	<vCard:Given>Sarah</vCard:Given>
    </vCard:N>
  </rdf:Description>

  <rdf:Description rdf:about="http://somewhere/MattJones">
    <vCard:FN>Matt Jones</vCard:FN>
    <vCard:N
	vCard:Family="Jones"
	vCard:Given="Matthew"/>
  </rdf:Description>

</rdf:RDF>

  我们查询所有年龄大于24岁的人,查询语句如下所示:

PREFIX info: <http://somewhere/peopleInfo#>

SELECT ?resource
WHERE
  {
    ?resource info:age ?age .
    FILTER (?age >= 24)
  }

  将上述查询语句保存为文件q-f2.rq,放到doc/Tutorial目录下。在终端执行命令:

sparql --data=vc-db-1.rdf --query=q-f2.rq

  返回查询结果如下图。
在这里插入图片描述

6 Optional Information

  RDF 是半结构化数据,RDF中不同的实体可能具有不同的属性。SPARQL可以查询RDF中存在的信息,但是在查询不存在的信息时并不会显示查询失败,也不会返回任何结果。可以使用Optional关键字,表示该查询是可选的,也就是当实体存在该属性时,就返回结果,不存在时就返回空。
  例如下面的查询语句:

PREFIX info:    <http://somewhere/peopleInfo#>
PREFIX vcard:   <http://www.w3.org/2001/vcard-rdf/3.0#>

SELECT ?name ?age
WHERE
{
    ?person vcard:FN  ?name .
    OPTIONAL { ?person info:age ?age }
}

  Optional后的三元组表示实体存在age属性时就返回该属性结果,不存在就返回空。将上述查询语句保存为文件q-opt1.rq,放到doc/Tutorial目录下。在终端执行命令:

sparql --data=vc-db-2.rdf --query=q-opt1.rq

  返回查询结果如下图。
在这里插入图片描述
  如果没有optional关键字,上述查询语句就不会返回没有age属性的实体。如下所示,删除optional后的查询语句:

PREFIX info:   <http://somewhere/peopleInfo#>
PREFIX vcard:  <http://www.w3.org/2001/vcard-rdf/3.0#>

SELECT ?name ?age
WHERE
{
    ?person vcard:FN  ?name .
    ?person info:age ?age .
}

  将上述查询语句保存为文件q-opt2.rq,放到doc/Tutorial目录下。在终端执行命令:

sparql --data=vc-db-2.rdf --query=q-opt2.rq

  返回查询结果如下图。
在这里插入图片描述
  Filter关键词也可以在optional中使用,如下所示:

PREFIX info:        <http://somewhere/peopleInfo#>
PREFIX vcard:      <http://www.w3.org/2001/vcard-rdf/3.0#>

SELECT ?name ?age
WHERE
{
    ?person vcard:FN  ?name .
    OPTIONAL { ?person info:age ?age . FILTER ( ?age > 24 ) }
}

  上述查询将filter关键词放在optional的三元组中,因此filter只对该三元组的结果有效。将上述查询语句保存为文件q-opt3.rq,放到doc/Tutorial目录下。在终端执行命令:

sparql --data=vc-db-2.rdf --query=q-opt3.rq

  返回查询结果如下图。
在这里插入图片描述
  如果将filter放到外面,filter将对所有返回结果都有效,例如:

PREFIX info:        <http://somewhere/peopleInfo#>
PREFIX vcard:      <http://www.w3.org/2001/vcard-rdf/3.0#>

SELECT ?name ?age
WHERE
{
    ?person vcard:FN  ?name .
    OPTIONAL { ?person info:age ?age . }
    FILTER ( !bound(?age) || ?age > 24 )
}

  Filter中的条件表示若实体存在age属性,则必须大于24,否则不返回。对于不存在age属性的实体,仍可以返回。这是因为!bound表示未绑定的意思,!bound(?age)意思是实体可以没有age属性。因此这个filter语句的含义是:保留age大于24的实体或者没有age属性的实体。将上述查询语句保存为文件q-opt4.rq,放到doc/Tutorial目录下。在终端执行命令:

sparql --data=vc-db-2.rdf --query=q-opt4.rq

  返回查询结果如下图。
在这里插入图片描述
  如果filter中没有!bound(?age),则只会返回一个结果,如下:
在这里插入图片描述

7 Alternatives in a Pattern

  有时我们需要联合多种条件进行查询,UNION关键词可以实现此目的。UNION用于联合多个查询三元组,只要实体满足其中一个三元组即可返回。本节使用的数据内容如下:

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

_:a foaf:name   "Matt Jones" .
_:b foaf:name   "Sarah Jones" .
_:c vcard:FN    "Becky Smith" .
_:d vcard:FN    "John Smith" .

  将上述内容保存为文件vc-db-3.ttl,放到doc/Tutorial目录下。查询语句如下:

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 }
}

  将上述查询语句保存为文件q-union1.rq,放到doc/Tutorial目录下。在终端执行命令:

sparql --data=vc-db-3.ttl --query=q-union1.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 )
}

  这种方式效率可能没有前一种快,这里是先查询出所有的实体,然后在进行过滤。将上述查询语句保存为文件q-union-1alt.rq,放到doc/Tutorial目录下。在终端执行命令:

sparql --data=vc-db-3.ttl --query=q-union-1alt.rq

  返回查询结果和上一个相同。

8 Datasets

  有时候一个graph中含有多个graph,例如下面的default graph中含有ds-ng-1.ttl和ds-ng-2.ttl。

@prefix dc: <http://purl.org/dc/elements/1.1/> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .

<ds-ng-1.ttl> dc:date "2005-07-14T03:18:56+0100"^^xsd:dateTime .
<ds-ng-2.ttl> dc:date "2005-09-22T05:53:05+0100"^^xsd:dateTime .

  ds-ng-1.ttl是一个named graph,其内容如下:

@prefix dc: <http://purl.org/dc/elements/1.1/> .

[] dc:title "Harry Potter and the Philospher's Stone" .
[] dc:title "Harry Potter and the Chamber of Secrets" .

  ds-ng-2.ttl是一个named graph,其内容如下:

@prefix dc: <http://purl.org/dc/elements/1.1/> .

[] dc:title "Harry Potter and the Sorcerer's Stone" .
[] dc:title "Harry Potter and the Chamber of Secrets" .

  返回default graph中的所有三元组,尽管default graph中引用了其他的named graph,这些named graph中的三元组是不会返回的。查询语句如下:

PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
PREFIX dc: <http://purl.org/dc/elements/1.1/>
PREFIX : <.>

SELECT *
{ ?s ?p ?o }

  其中的“PREFIX : <.>” 仅是为了简化输出格式。将上述查询语句保存为文件q-ds-1.rq,放到doc/Tutorial目录下。在终端执行命令:

sparql --data=ds-dft.ttl --query=q-ds-1.rq

  返回查询结果如下。
在这里插入图片描述
  下面的查询语句将返回引用的named graph内容。查询语句如下所示:

PREFIX  xsd:    <http://www.w3.org/2001/XMLSchema#>
PREFIX  dc:     <http://purl.org/dc/elements/1.1/>
PREFIX  :       <.>

SELECT *
{
    { ?s ?p ?o } UNION { GRAPH ?g { ?s ?p ?o } }
}

  GRPHA关键词表示变量g是一个named graph。将上述查询语句保存为文件q-ds-2.rq,放到doc/Tutorial目录下。在终端执行命令:

sparql --data=ds-dft.ttl --query=q-ds-2.rq --graph ds-dft.ttl --namedgraph ds-ng-1.ttl --namedgraph ds-ng-2.ttl

  返回查询结果如下。
在这里插入图片描述
  也可以指定查询某个named graph,如下查询语句指定查询ds-ng-2.ttl。

PREFIX dc: <http://purl.org/dc/elements/1.1/>
PREFIX : <.>

SELECT ?title
{
  GRAPH :ds-ng-2.ttl
    { ?b dc:title ?title }
}

  将上述查询语句保存为文件q-ds-3.rq,放到doc/Tutorial目录下。在终端执行命令:

sparql --data=ds-dft.ttl --query=q-ds-3.rq --graph ds-dft.ttl --namedgraph ds-ng-1.ttl --namedgraph ds-ng-2.ttl

  返回查询结果如下。
在这里插入图片描述
  Named graph也可以作为一个变量,使用条件查询来选择named graph。查询语句如下:

PREFIX  xsd:    <http://www.w3.org/2001/XMLSchema#>
PREFIX  dc:     <http://purl.org/dc/elements/1.1/>
PREFIX  :       <.>

SELECT ?date ?title
{
  ?g dc:date ?date . FILTER (?date > "2005-08-01T00:00:00Z"^^xsd:dateTime )
  GRAPH ?g
      { ?b dc:title ?title }
}

  Filter关键词筛选变量g,然后将g作为named graph。将上述查询语句保存为文件q-ds-4.rq,放到doc/Tutorial目录下。在终端执行命令:

sparql --data=ds-dft.ttl --query=q-ds-4.rq --graph ds-dft.ttl --namedgraph ds-ng-1.ttl --namedgraph ds-ng-2.ttl

  返回查询结果如下。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值