首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

用 SPARQL 搜索 RDF 数据(1)

用 SPARQL 搜索 RDF 数据(1)

资源描述框架(Resource Description Framework),或 RDF,能够将数据打散并分布开来。RDF 模型可以容易地合并在一起,而且序列化的 RDF 也可以简单地通过 HTTP 交换。应用程序可以通过 Web 松散地耦合到多个 RDF 数据源上。例如,在 PlanetRDF.com 上,我们把多个作者的 weblog 集中起来,作者们在 RSS 1.0 feed 中用 RDF 提供内容。作者 feed 的 URL 本身就放在 RDF 图中,叫作 bloggers.rdf
但是怎样才能在 RDF 图中发现并操纵需要的数据呢?SPARQL 协议和 RDF 查询语言(SPARQL)目前是 W3C 的工作草案,还在讨论当中。SPARQL 构建在以前的 RDF 查询语言(例如 rdfDB、RDQL 和 SeRQL)之上,拥有一些有价值的新特性。在本文中,我们将用三种驱动 PlanetRDF 的 RDF 图  ——  描述作者的 FOAF 图、他们的 RSS 1.0 feed 以及 bloggers 图  ——  来演示 SPARQL 能对数据做的一些有意思的事情。SPARQL 拥有针对各种平台和语言的实现;本文将重点介绍面向 Java 平台的 Jena 语义 Web 工具包。
本文假设您有 RDF 的工作知识,熟悉 RDF 的词汇(例如 Dublin Core、FOAF 和 RSS 1.0)。此外,本文还假设您有一些使用 Jena 语义 Web 工具包的经验。要想跟上所有这些技术的发展速度,请参阅后面  部分中的链接。
一个简单 SPARQL 查询的剖析我们首先从查看 PlanetRDF 的 bloggers.rdf 模型开始。该模型非常简单,通过 FOAF 和 Dublin Core 词汇为每个 blog 投稿者提供名称、blog 标题和 URL。图 1 显示了一个投稿者的基本图结构。完整的模型只是为我们汇集的每一篇 blog 日志重复这个结构而已。
图 1. bloggers.rdf 中的一个投稿者的基本图结构现在,我们来看一个针对博客模型的非常简单的 SPARQL 查询。比方说以下这个查询“根据名为 Jon Foobar 的人查找 blog 的 URL”,如清单 1 所示:
清单 1. 查找某一投稿者的 blog 的 URL 的 SPARQL 查询
1
2
3
4
5
6
7
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
SELECT ?url
FROM    <bloggers.rdf>
WHERE  {
    ?contributor foaf:name "Jon Foobar" .
    ?contributor foaf:weblog ?url .
}




查询的第一行只是为 FOAF 定义 PREFIX,这样就不必每次都用完整名称引用它。SELECT 子句指定查询应当返回的内容,在这个例子中,返回的是名为 url 的变量。SPARQL 变量用 ? 或 $作为前缀,这两个前缀是可以互换的,但在本文中,我坚持使用 ? 作为前缀。FROM 是一个可选的子句,它提供了将要使用的数据集的 URI。在这里,它只是指向一个本地文件,但是它也可以指向 Web 其他地方的某一个图的 URL。最后,WHERE 子句由一组三元模式组成,用基于 Turtle 的语法表示。这些三元模式共同构成了所谓的图形模式
这个查询试图把图形模式的三元模式和模型进行匹配。将每个图形模式变量的绑定与模型节点进行匹配就成为一种查询解决方案,而 SELECT 子句中指定的变量值则成为查询结果的一部分。
在这个示例中,WHERE 子句的图形模式中的第一个三元组与 foaf:name 属性为“Jon Foobar”的节点匹配,并把它绑定到名为 contributor 的变量。在 bloggers.rdf 模型中,contributor 会和 图 1 顶部的空节点  foaf:Agent 匹配。图形模式的第二个三元组与 contributor 的 foaf:weblog 属性对应的对象匹配。这被绑定到 url 变量,形成查询结果。
在 Jena 中使用 SPARQL 支持在 Jena 中使用 SPARQL 目前可以通过叫作 ARQ 的模块得以实现。除了实现 SPARQL 之外,ARQ 的查询引擎还可以解析使用 RDQL 或者它自己内部的查询语言表示的查询。ARQ 的开发很活跃,但它还不是标准 Jena 发行版本中的一部分。但是,可以从 Jena 的 CVS 仓库或者自包含的下载文件中获得它。
让 ARQ 运行起来很简单。只需要得到最新的 ARQ 发行包(要获得有关链接,请参阅后面  部分),然后对其进行解压,把环境变量 ARQROOT 设置成指向 ARQ 目录即可。可能还需要恢复 ARQ bin 目录的读取和执行权限。如果把 bin 目录添加到执行路径中非常方便,那是因为它包含从命令行调用  ARQ 的包装器脚本。为了确定所有设置都已到位,请从命令行调用 sparql,确定看到了它的用法信息。清单 2 演示了所有步骤,清单 2 假设正在 UNIX 类的平台上工作,或者是在 Windows 下用 Cygwin 工作。(ARQ 还附带了在 Windows 下使用的.bat 脚本,但是它们用法和下面示例中的用法稍有差别。)
清单 2. 设置使用 Jena ARQ 的环境
1
2
3
4
5
$ export ARQROOT=~/ARQ-0.9.5
$ chmod +rx $ARQROOT/bin/*
$ export PATH=$PATHARQROOT/bin
$ sparql
    Usage: [--data URL] [exprString | --query file]




从命令行执行 SPARQL 查询现在就可以运行 SPARQL 查询了(参见清单 3)。我们将使用来自 的数据集和查询。因为查询使用 FROM 关键字指定要使用的图,所以只需把查询文件的位置提供给 sparql 命令行即可。但是,查询需要在包含图的目录中运行,因为该图是在查询的 FROM 子句中用相对 URL 指定的。
清单 3. 用 sparql 命令执行简单查询
1
2
3
4
5
6
$ sparql --query jon-url.rq
----------------------------
| url                      |
============================
| <http://foobar.xx/blog>  |
----------------------------




有时,从查询中忽略 FROM 子句很有意义。这样就可以允许在执行查询的时候才把图传递给它。当从应用程序代码中使用 SPARQL 时,避免把数据集绑定到查询是一个好习惯 —— 例如,它允许把同一查询重用在不同的图上。可以在命令行用 sparql --data URL 选项在运行时指定图,其中 URL 是图的位置。这个 URL 既可以是本地文件的位置,也可以是远程图的 Web 地址。
用 Jena API 执行 SPARQL 查询命令行 sparql 工具对于运行独立查询有用,同时 Java 应用程序也可以直接调用 Jena 的 SPARQL 功能。通过 com.hp.hpl.jena.query 包中的类,使用 Jena 来创建和执行 SPARQL 查询。使用 QueryFactory 是最简单的方法。QueryFactory 有各种 create() 方法,用来从文件或者 String 读取文本查询。这些 create() 方法返回 Query 对象,这个对象封装了解析后的查询。
下一步是创建 QueryExecution 的实例,这个类表示查询的一个执行。要获得 QueryExecution,请调用 QueryExecutionFactory.create(query, model),并传入要执行的 Query 以及查询要处理的 Model。因为查询的数据是编程方式提供的,所以查询不需要 FROM 子句。
QueryExecution 上有几种不同的执行方法,每个方法执行一种不同类型的查询(请参阅标题为“”的侧栏,以获得更多信息)。对于简单的 SELECT 查询,可以调用 execSelect(),该方法将返回 ResultSet。ResultSet 支持在查询返回的每个 QuerySolution 上进行迭代,这提供了对每个绑定变量值的访问。另外,还可以使用 ResultSetFormatter,以不同的格式输出查询结果。
清单 4 显示了一个把这些步骤放在一起的简单方法。它执行一个针对 bloggers.rdf 的查询,并把结果输出到控制台。
清间 4.用 Jena API 执行一个简单查询
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// Open the bloggers RDF graph from the filesystem
InputStream in = new FileInputStream(new File("bloggers.rdf"));
// Create an empty in-memory model and populate it from the graph
Model model = ModelFactory.createMemModelMaker().createModel();
model.read(in,null); // null base URI, since model URIs are absolute
in.close();
// Create a new query
String queryString =
    "REFIX foaf: <http://xmlns.com/foaf/0.1/> " +
    "SELECT ?url " +
    "WHERE {" +
    "      ?contributor foaf:name \"Jon Foobar\" . " +
    "      ?contributor foaf:weblog ?url . " +
    "      }";
Query query = QueryFactory.create(queryString);
// Execute the query and obtain results
QueryExecution qe = QueryExecutionFactory.create(query, model);
ResultSet results = qe.execSelect();
// Output query results
ResultSetFormatter.out(System.out, results, query);
// Important - free up resources used running the query
qe.close();

返回列表