ARQ 是 Jena 用以支持 SPARQL 的 查询引擎。本文将通过使用 ARQ 进行实际的 SPARQL 查询操作,来对 SPARQL 进行介绍。
数据源
在使用 ARQ 之前,让我们先来介绍一下我们所使用的RDF 数据源。数据的结构如下图所示。
该模型保存为一个 RDF 文件。
vc-db-1.rdf
- <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#'
- >
- <rdf:Description rdf:about="http://somewhere/JohnSmith/">
- <vCard:FN>John Smith</vCard:FN>
- <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>
- <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>
用三元组的形式表示为:
- @prefix vCard: <http://www.w3.org/2001/vcard-rdf/3.0#> .
- @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
- @prefix : <#> .
- <http://somewhere/MattJones/>
- vCard:FN "Matt Jones" ;
- vCard:N [ vCard:Family
- "Jones" ;
- vCard:Given
- "Matthew"
- ] .
- <http://somewhere/RebeccaSmith/>
- vCard:FN "Becky Smith" ;
- vCard:N [ vCard:Family
- "Smith" ;
- vCard:Given
- "Rebecca"
- ] .
- <http://somewhere/JohnSmith/>
- vCard:FN "John Smith" ;
- vCard:N [ vCard:Family
- "Smith" ;
- vCard:Given
- "John"
- ] .
- <http://somewhere/SarahJones/>
- vCard:FN "Sarah Jones" ;
- vCard:N [ vCard:Family
- "Jones" ;
- vCard:Given
- "Sarah"
- ] .
也可以这样表示:
- @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" .
ARQ ---- Jena 的 SPARQL 工具
在我们下载得到的Jena 包的bat 或 bin 目录下,具有文件 sparql.bat 或 sparql 。我们可以使用它们进行 SPARQL 查询操作。
我们所使用的查询文件为:
q1.rq
- SELECT ?x
- WHERE { ?x <http://www.w3.org/2001/vcard-rdf/3.0#FN> "John Smith" }
在执行操作之前,首先需要设置 JENAROOT 环境变量。将其设置为Jena 包解压后的位置。然后就可以执行查询操作了。如下图所示:
可以看出,我们首先将 JENAROOT 设置为 D:\Workspaces\JenaDemo\apache-jena-2.7.4,这是 Jena 包的位置。
然后执行 bat\sparql.bat --data=vc-db-1.rdf --query=q1.rq。可以看出查询得到一个结果,x 为 <http://somewhere/JohnSmith>。
Solution ---- 查询结果
Query Solutions 是查询所得到的一些“变量/值”对的集合。
看下面这个查询:
- SELECT ?x ?fname
- WHERE {?x <http://www.w3.org/2001/vcard-rdf/3.0#FN> ?fname}
它的结果为:
- ----------------------------------------------------
- | x | name |
- ====================================================
- | <http://somewhere/RebeccaSmith/> | "Becky Smith" |
- | <http://somewhere/SarahJones/> | "Sarah Jones" |
- | <http://somewhere/JohnSmith/> | "John Smith" |
- | <http://somewhere/MattJones/> | "Matt Jones" |
- ----------------------------------------------------
得到了 4 个solution。
基本模式(Basic Pattern)
基本模式时一些三元组模式(Triple Patterns)的集合。如下 SPARQL 语句:
- 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 .
- }
仅当一次查询中所有的三元组都与同一个值 match 的时候,我们才说它同这个值 match。如这个 SPARQL 语句查询所得到的结果为:
- -------------
- | givenName |
- =============
- | "John" |
- | "Rebecca" |
- -------------
看这个例子
- PREFIX vcard: <http://www.w3.org/2001/vcard-rdf/3.0#>
- SELECT ?givenName
- WHERE
- { ?y vcard:Family "Smith" .
- ?y vcard:Given ?givenName .
- }
- PREFIX vcard: <http://www.w3.org/2001/vcard-rdf/3.0#>
- SELECT ?y ?givenName
- WHERE
- { ?y vcard:Family "Smith" .
- ?y vcard:Given ?givenName .
- }
查询得到的结果为:
- --------------------
- | y | givenName |
- ====================
- | _:b0 | "John" |
- | _:b1 | "Rebecca" |
- --------------------
以 "_:" 开头的QName 并不是空节点的内部表示,它们仅仅是 ARQ 所打印出来的一个标记而已。
字符串匹配
语法为:
- FILTER regex(?x, "pattern" [, "flags"])
其中 flags 如果是 "i" ,就代表忽略大小写。看下面这个例子
- 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" 的项。
值匹配
- PREFIX info: <http://somewhere/peopleInfo#>
- SELECT ?resource
- WHERE
- {
- ?resource info:age ?age .
- FILTER (?age >= 24)
- }
其中 age 的类型为 integer。如下例中 "^^xsd:integer" 所表示的:
- <http://somewhere/RebeccaSmith/>
- info:age "23"^^xsd:integer ;
- vCard:FN "Becky Smith" ;
- vCard:N [ vCard:Family "Smith" ;
- vCard:Given "Rebecca" ] .
可选项
OPTIONAL 使得当某一项不存在时查询不至于失败。
如下查询获取 name 和 age(仅当age 存在时才获取,弱age 不存在只获取name)。
- 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 }
- }
查询结果为:
- ------------------------
- | name | age |
- =======================
- | "Becky Smith" | 23 |
- | "Sarah Jones" | |
- | "John Smith" | 25 |
- | "Matt Jones" | |
- -----------------------
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" .
查询
- 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" |
- | "Becky Smith" |
- | "John Smith" |
- -----------------
而如果分别用 name1 和name2,则
- 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" | |
- | | "Becky Smith" |
- | | "John Smith" |
- ---------------------------------