用 SPARQL 搜索 RDF 数据Word下载.docx
《用 SPARQL 搜索 RDF 数据Word下载.docx》由会员分享,可在线阅读,更多相关《用 SPARQL 搜索 RDF 数据Word下载.docx(14页珍藏版)》请在冰豆网上搜索。
图1.bloggers.rdf中的一个投稿者的基本图结构
现在,我们来看一个针对博客模型的非常简单的SPARQL查询。
比方说以下这个查询“根据名为JonFoobar的人查找blog的URL”,如清单1所示:
清单1.查找某一投稿者的blog的URL的SPARQL查询
PREFIXfoaf:
<
SELECT?
url
FROM<
bloggers.rdf>
WHERE{
?
contributorfoaf:
name"
JonFoobar"
.
weblog?
url.
}
查询的第一行只是为FOAF定义
PREFIX,这样就不必每次都用完整名称引用它。
SELECT
子句指定查询应当返回的内容,在这个例子中,返回的是名为
url
的变量。
SPARQL变量用
?
或
$作为前缀,这两个前缀是可以互换的,但在本文中,我坚持使用
作为前缀。
FROM
是一个可选的子句,它提供了将要使用的数据集的URI。
在这里,它只是指向一个本地文件,但是它也可以指向Web其他地方的某一个图的URL。
最后,WHERE
子句由一组三元模式组成,用基于Turtle的语法表示。
这些三元模式共同构成了所谓的图形模式。
这个查询试图把图形模式的三元模式和模型进行匹配。
将每个图形模式变量的绑定与模型节点进行匹配就成为一种查询解决方案,而SELECT
子句中指定的变量值则成为查询结果的一部分。
在这个示例中,WHERE
子句的图形模式中的第一个三元组与
foaf:
name
属性为“JonFoobar”的节点匹配,并把它绑定到名为contributor
在bloggers.rdf模型中,contributor
会和
图1
顶部的空节点
Agent
匹配。
图形模式的第二个三元组与contributor
的
weblog
属性对应的对象匹配。
这被绑定到
变量,形成查询结果。
回页首
在Jena中使用SPARQL
支持在Jena中使用SPARQL目前可以通过叫作
ARQ
的模块得以实现。
除了实现SPARQL之外,ARQ的查询引擎还可以解析使用RDQL或者它自己内部的查询语言表示的查询。
ARQ的开发很活跃,但它还不是标准Jena发行版本中的一部分。
但是,可以从Jena的CVS仓库或者自包含的下载文件中获得它。
让ARQ运行起来很简单。
只需要得到最新的ARQ发行包(要获得有关链接,请参阅后面
部分),然后对其进行解压,把环境变量
ARQROOT
设置成指向ARQ目录即可。
可能还需要恢复ARQbin目录的读取和执行权限。
如果把bin目录添加到执行路径中非常方便,那是因为它包含从命令行调用ARQ的包装器脚本。
为了确定所有设置都已到位,请从命令行调用
sparql,确定看到了它的用法信息。
清单2演示了所有步骤,清单2假设正在UNIX类的平台上工作,或者是在Windows下用Cygwin工作。
(ARQ还附带了在Windows下使用的.bat
脚本,但是它们用法和下面示例中的用法稍有差别。
)
清单2.设置使用JenaARQ的环境
$exportARQROOT=~/ARQ-0.9.5
$chmod+rx$ARQROOT/bin/*
$exportPATH=$PATH:
$ARQROOT/bin
$sparql
Usage:
[--dataURL][exprString|--queryfile]
从命令行执行SPARQL查询
现在就可以运行SPARQL查询了(参见清单3)。
我们将使用来自
清单1的数据集和查询。
因为查询使用
关键字指定要使用的图,所以只需把查询文件的位置提供给
sparql
命令行即可。
但是,查询需要在包含图的目录中运行,因为该图是在查询的
子句中用相对URL指定的。
清单3.用sparql命令执行简单查询
$sparql--queryjon-url.rq
----------------------------
|url|
============================
|<
http:
//foobar.xx/blog>
|
有时,从查询中忽略
子句很有意义。
这样就可以允许在执行查询的时候才把图传递给它。
当从应用程序代码中使用SPARQL时,避免把数据集绑定到查询是一个好习惯——例如,它允许把同一查询重用在不同的图上。
可以在命令行用
sparql--dataURL选项在运行时指定图,其中
URL
是图的位置。
这个URL既可以是本地文件的位置,也可以是远程图的Web地址。
用JenaAPI执行SPARQL查询
命令行
工具对于运行独立查询有用,同时Java应用程序也可以直接调用Jena的SPARQL功能。
通过com.hp.hpl.jena.query
包中的类,使用Jena来创建和执行SPARQL查询。
使用
QueryFactory
是最简单的方法。
有各种
create()
方法,用来从文件或者
String
读取文本查询。
这些
方法返回
Query
对象,这个对象封装了解析后的查询。
下一步是创建
QueryExecution
的实例,这个类表示查询的一个执行。
要获得
QueryExecution,请调用QueryExecutionFactory.create(query,model),并传入要执行的
以及查询要处理的
Model。
因为查询的数据是编程方式提供的,所以查询不需要
子句。
上有几种不同的执行方法,每个方法执行一种不同类型的查询(请参阅标题为“其他类型的SPARQL查询”的侧栏,以获得更多信息)。
对于简单的
查询,可以调用
execSelect(),该方法将返回
ResultSet。
ResultSet
支持在查询返回的每个QuerySolution
上进行迭代,这提供了对每个绑定变量值的访问。
另外,还可以使用
ResultSetFormatter,以不同的格式输出查询结果。
清单4显示了一个把这些步骤放在一起的简单方法。
它执行一个针对bloggers.rdf的查询,并把结果输出到控制台。
清间4.用JenaAPI执行一个简单查询
//OpenthebloggersRDFgraphfromthefilesystem
InputStreamin=newFileInputStream(newFile("
bloggers.rdf"
));
//Createanemptyin-memorymodelandpopulateitfromthegraph
Modelmodel=ModelFactory.createMemModelMaker().createModel();
model.read(in,null);
//nullbaseURI,sincemodelURIsareabsolute
in.close();
//Createanewquery
StringqueryString=
"
+
url"
WHERE{"
name\"
JonFoobar\"
."
url."
}"
;
Queryquery=QueryFactory.create(queryString);
//Executethequeryandobtainresults
QueryExecutionqe=QueryExecutionFactory.create(query,model);
ResultSetresults=qe.execSelect();
//Outputqueryresults
ResultSetFormatter.out(System.out,results,query);
//Important-freeupresourcesusedrunningthequery
qe.close();
编写更复杂的查询
迄今为止,您已经看到了两种运行简单SPARQL查询的方法:
用命令行
工具,用Java代码调用JenaAPI。
在这一节中,我将介绍更多SPARQL的特性,以及它们支持的更复杂的查询。
RDF经常被用来表示半结构化的
数据。
这意味着在一个模型中,两个相同类型的节点可能有两个不同的属性集。
例如,在FOAF模型中,对人的描述可能只包含电子邮件地址;
而作为另一个选择,它也可以包含真实名称、IRC昵称、描绘个人照片的URL,等等。
提炼查询结果
为了进一步提炼查询的结果,SPARQL拥有DISTINCT、LIMIT、OFFSET
和
ORDERBY
关键字,它们操作或多或少与它们在SQL中的对应物有些类似。
DISTINCT可能只用在
查询上,格式为
SELECTDISTINCT。
它会从结果集中清除重复的查询结果,让留下的每个结果都是惟一的。
其他关键字都放在查询的
WHERE
子句之后。
LIMIT
n
把查询返回的结果数量限制在
n个,
而OFFSET
则忽略前面
个结果。
ORDERBY?
var
会根据
的自然顺序对结果进行排序,例如,如果
是字符串值,则按字母顺序排序。
可以用
ASC[?
var]
DESC[?
指定排序的方向。
当然,可以把
DISTINCT、LIMIT、OFFSET
组合在查询中。
例如,可以用
ORDERBYDESC[?
date]LIMIT10
找到RSSfeed中最新的十个条目。
清单5显示了一个非常小的FOAF图,用Turtle语法表示。
它包含对4个虚构人物的描述,但是每个描述都有不同的属性集。
清单5.一个描述4个虚构人物的小FOAF图
@prefixfoaf:
_:
afoaf:
;
foaf:
mbox<
mailto:
jon@foobar.xx>
depiction<
//foobar.xx/2005/04/jon.jpg>
bfoaf:
A.N.O'
Ther"
a.n.other@>
cfoaf:
LizSomebody"
mbox_sha1sum"
3f01fa9929df769aff173f57dec2fe0c2290aeea"
dfoaf:
MBenn"
//mbe.nn/pics/me.jpeg>
可选匹配
假设您想编写一个查询,返回清单5的图中所描述的每个人的名字,以及每个人的照片的链接(如果有照片的话)。
在foaf:
depiction
中包含的图形模式的
查询可能只会发现三个结果。
LizSomebody不会形成结果,因为虽然它有
name属性,但它没有
属性,而如果要与查询匹配的话,那么这两个属性都需要。
帮助就在眼前,就是SPARQL的
OPTIONAL
关键字。
可选块
定义了附加图形模式,即使模式不匹配,不会造成结果被拒绝,但在匹配的时候,图形模式会被绑定到图形上。
清单6演示了一个查询,在清单5的FOAF数据中查找每个人的
name,而且可以选择性地查找伴随的
depiction。
清单6.用可选块查询FOAF数据
name?
depiction
WHERE{
personfoaf:
name.
OPTIONAL{
depiction?
depiction.
}.
}
清单7显示了运行清单6的查询的结果。
所有查询结果都包含人名,可选的图形模式则只在
属性存在的时候才绑定;
如果没有,就从结果中忽略。
从这种意义上说,查询与SQL中的左外连接相似。
清单7.清单6的查询结果
------------------------------------------------------------
|name|depiction|
============================================================
|"
|<
|
||
可选块可以包含任何图形模式,不仅仅是像清单6所示的那种单一的三元模式。
可选块中的所有查询模式都匹配,才能让可选模式成为查询结果的一部分。
如果查询有多个可选块,那么它们会分别发挥作用——可能在结果中被忽略,也可能存在于结果中。
可选块也可以嵌套,在这种情况下,只有外部可选块的模式与图形匹配时,才考虑内部可选块。
替换匹配
FOAF图形用人们的电子邮件地址来惟一地标识他们。
出于隐私的考虑,有些人喜欢用电子邮件地址的哈希码。
纯文本的电子邮件地址用
mbox
属性表示,而电子邮件地址的哈希码则用
mbox_sha1sum
属性表示;
这两个属性在人们的FOAF描述中通常是互斥的。
在这种情况下,可以用SPARQL的
替代匹配
特性来编写查询,该查询返回任何可用的属性。
替换匹配的定义方式是写出多个替换图形模式,中间用
UNION
关键字连接。
清单8显示的查询在
清单5
中的FOAF中查找每个人的名字,以及他们的
mbox_sha1sum。
MBenn不是查询结果,因为它既没有
属性也没有foaf:
属性。
与
图形模式相比,至少
要有一个替换模式和某个查询结果匹配;
如果UNION
匹配中的分支都匹配,那么会生成两个结果。
清单8.有替代匹配的查询和查询结果
PREFIXrdf:
//www.w3.org/1999/02/22-rdf-syntax-ns#>
mbox
{
{?
mbox?
mbox}UNION{?
mbox_sha1sum?
mbox}
---------------------------------------------------------------------
|name|mbox|
=====================================================================
|"
值约束条件
SPARQL中的
FILTER
关键字对绑定变量的值进行约束,从而限制查询的结果。
这些值约束条件是对布尔值进行计算的逻辑表达式,并且可以与逻辑操作符
&
||
组合使用。
例如,可以用过滤器把返回名称列表的查询修改成只返回和指定正则表达式匹配的名称。
或者,如清单9所示,过滤器在项目的出版日期上设置限制,从而找到RSSfeed中在两个特定日期之间发布的项目。
清单9还显示了如何使用SPARQL的XPath样式的类型转换特性(在这里,是将
date
变量转换成XMLSchema的
dateTime
值),以及如何用^^xsd:
在文字日期字符串上指定相同的数据类型。
这可以确保在查询中使用日期比较,而不是标准的字符串比较。
清单9.用过滤器检索在2005年4月发布的RSSfeed项目
PREFIXrss:
//purl.org/rss/1.0/>
PREFIXxsd:
//www.w3.org/2001/XMLSchema#>
PREFIXdc:
//purl.org/dc/elements/1.1/>
item_title?
pub_date
itemrss:
title?
item_title.
itemdc:
date?
pub_date.
FILTERxsd:
dateTime(?
pub_date)>
="
2005-04-01T00:
00:
00Z"
^^xsd:
dateTime&
xsd:
pub_date)<
2005-05-01T00:
dateTime
处理多个图形
迄今为止,我所演示的所有查询只包含一个RDF图的数据集。
在SPARQL的术语中,这些查询针对的是
后台图(backgroundgraph)。
后台图是指:
在使用Jena的API时,通过某个查询的
子句、sparql
命令的
--data
开关或者通过向QueryExecutionFactory.create()
传递一个模型来指定的图。
其他类型的SPARQL查询
除了本文使用的
查询之外,SPARQL还支持另外三种查询。
如果查询的图形模式在数据集中有匹配物,那么
ASK
将返回“yes”,如果没有匹配物,则返回“no”。
DESCRIBE
返回一个图形,其中包含和图形模式匹配的节点的相关信息。
例如,DESCRIBE?
personWHERE{?
}
会返回一个图,其中包括来自JonFoobar的模型的三元模式。
最后,CONSTRUCT
用来为每个查询结果输出一个图形模式。
这样就可以直接从查询结果创建新的RDF图。
可以把RDF图上的
CONSTRUCT
查询想像成与XML数据的