RDF数据查询语言SPARQL

 数据源,一个RDF文件,就是帮助文档中的vc-db-1.rdf,文档描述了一些简单的人名信息,下面是类似三元组形式的数据表示。

2.2   查询语句q1.rq,记事本创建一个文件,内容如下,文件保存为q1.rq。注意文件后缀是.rq,不是.txt。

SELECT ?x
WHERE { ?x <http://www.w3.org/2001/vcard-rdf/3.0#FN> "John Smith" }
2.3   那么使用上面的查询语句查询vc-db-1.rdf文件中的数据的命令行语句就是

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

返回结果是:

| x                             |
=================================
| <http://somewhere/JohnSmith/> |
在执行上面的查询时,要保证数据文件和查询文件在当前目录下,否则命令中应该包括完整路径,即:

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

2.4   对查询语句和查询结果的理解

查询语句包括查询信息的名称以及名称应该符合的条件。条件子句以三元组形式出现,按照<主语,谓语,宾语>的顺序排列。查询条件也成为一个模式(Pattern)。查询的结果实际就是条件三元组与数据文件(或RDF图)中RDF三元组匹配的结果。

语句中的 ? 加一个字母表示该字母是一个变量,比如 ?x,在SELECT后面的变量会显示在查询结果中,作为列名称出现。

3.      命名空间的简写替代

如果查询所有具有名字的实例以及该实例的名字,那么查询语句如下

SELECT ?x ?fname
WHERE {?x <http://www.w3.org/2001/vcard-rdf/3.0#FN> ?fname}
注意,“?x ?fname”之间是空格,不是逗号。如果有多个模式三元组,那么三元组之间用点号“.”隔开,比如

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 .
}
这时候,模式中的谓词的URI都带一个长长的命名空间字符串,“http://www.w3.org/2001/vcard-rdf/3.0#”,能用一个简单的单词代替它应该会比较简单。实现简写URI的的语法是这样的:

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# 定义了一个前缀单词vcard,在查询语句中,它与后面的命名空间等价。

4.      过滤查询结果

在查询语句中添加过滤条件的语句是

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

FILTER是声明过滤, ?x是过滤模式作用的变量,后面的pattern是具体的限制条件,比如

PREFIX vcard: <http://www.w3.org/2001/vcard-rdf/3.0#>
SELECT ?g
WHERE
{ ?y vcard:Given ?g .
FILTER regex(?g, "r", "i") }
这是要查询一些名字(Given Name),”r”表示,名字中必须出现的字母”r”或者”R”;”i”表示,对签名的字母限制,对大小写并不敏感。若是要对大小写敏感,则去掉这个限制即可,即FILTER regex(?g, "r")。

上面查询的结果是

| g         |
=============
| "Rebecca" |
| "Sarah"   |
对数值限制的一个例子是:

PREFIX info <http://somewhere/peopleInfo#>
SELECT ?resource
WHERE { ?resource info:age ?age .
    FILTER (?age >= 24)}
注意,在RDF文件vc-db-1.rdf中并没有包括年龄age信息,这里要查询vc-db-2.rdf文件,即

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

查询结果是

| resource                      |
=================================
| <http://somewhere/JohnSmith/> |
5.      可选的查询信息optional information

5.1 简单的可选信息

在一些查询中,一些需要返回的数据可能不存在,而这些不存在的数据所在的数据元素中有其他需要返回的信息,这时候就可以通过可选查询信息进行查询,比如:

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表示,模式 { ?person info:age ?age } 是可选的,不是必须满足的。这个查询的执行语句是

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

查询结果是

| name          | age |
=======================
| "Becky Smith" | 23 |
| "Sarah Jones" |     |
| "John Smith" | 25 |
| "Matt Jones"|     |
如果去点关键字OPTIONAL,那么,查询的结果就
| name          | age |
=======================
| "Becky Smith" | 23 |
| "John Smith" | 25 |
有些人没有年龄信息,那么,这些人的名字也不会被作为查询结果返回。

5.2 对可选模式添加过滤条件

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 ) }
}
这样返回的信息是

| name          | age |
=======================
| "Becky Smith" |     |
| "Sarah Jones" |     |
| "John Smith" | 25 |
| "Matt Jones" |     |
有些人没有年龄信息("Sarah Jones"和"Matt Jones" ),有些人的年龄小于24("Becky Smith"),他们的名字信息也会出现在查询结果中。下面的查询要求,如果有年龄信息,那么年龄必须大于24,否则不是期望的查询结果。

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 )
}
语句 !bound(?age) || ?age > 24 的意思是,没有(未绑定)age或者age大于24。如此,年龄小于24的"Becky Smith"就不会出现在这个查询的结果中了。

| name          | age |
=======================
| "Sarah Jones" |     |
| "John Smith" | 25 |
| "Matt Jones" |     |
6.      联合查询

vCard词汇表和FOAF词汇表都可以表示人的信息,比如vCard中的 vCard:FN, FOAF中的 foaf:name.这一节介绍在一个RDF图同时用vCard:FN和 foaf:name表示人的信息时,如何查询相关数据。

注:vCard是电子商务中卡的一种文件格式标准,一般与邮件信息关联。FOAF(http://xmlns.com/foaf/0.1/)是一种RDF的应用,所列网址有它的规范。

6.1 一个RDF图文件,vc-db-3.ttl,文件的的内容为

@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" .
它只是分别用foaf:name 和vcard:FN描述了四个人名,这一节的查询将针对此文件。

6.2 查询人名信息

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" |
一个等价的查询语句是

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 ) }
6.3 记录结果的来源,查询语句和结果分别是

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" |
6.4 同时使用OPTIONAL和UNION

查询语句是

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" |               |
|               | "Becky Smith" |
|               | "John Smith" |
7. 查询命名的图

图是一个RDF数据集,不是一个完整的RDF文件。现在有三个图

Default graph (ds-dft.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 .
Named graph (ds-ng-1.ttl):

@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" .
Named graph (ds-ng-2.ttl):

@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" .
7.1 查询语句是

PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
PREFIX dc: <http://purl.org/dc/elements/1.1/>
PREFIX : <.>
SELECT *{ ?s ?p ?o }
对图的查询是(PREFIX : <.>是为了格式化输出???),

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

查询结果是

| s            | p       | o                                         |
======================================================================
| :ds-ng-2.ttl | dc:date | "2005-09-22T05:53:05+01:00"^^xsd:dateTime |
| :ds-ng-1.ttl | dc:date | "2005-07-14T03:18:56+01:00"^^xsd:dateTime |

7.2 查询指定图
PREFIX dc: <http://purl.org/dc/elements/1.1/>
PREFIX : <.>
SELECT ?title{
GRAPH :ds-ng-2.ttl
    { ?b dc:title ?title }}
查询结果

| title                                     |
=============================================
| "Harry Potter and the Sorcerer's Stone"   |
| "Harry Potter and the Chamber of Secrets" |
. SPARQL查询结果集

四种形式的结果

¨          SELECT – 返回一个表(table),Tutorial里介绍的主要是这种查询

¨          CONSTRUCT – 返回一个RDF图

¨          DESCRIBE – 返回一个RDF图.

¨          ASK – 布尔查询

结果调整

¨          Projection 投影- keep only selected variables 只保持选择的变量

¨          OFFSET/LIMIT 偏移和限制 - chop the number solutions (best used with ORDER BY) 分解数字结果

¨          ORDER BY 排序- sorted results(同数据类型类的结果???)

¨          DISTINCT - yield only one row for one combination of variables and values.

9. 在Jena中使用SPARQL

在我的机器上,eclipse已经可以运行使用Jena API的Java程序。这样就可以直接编写SPARQL查询程序。一个简单查询的全部代码如下:

import java.io.*;

import com.hp.hpl.jena.query.Query;
import com.hp.hpl.jena.ontology.OntModel;
import com.hp.hpl.jena.ontology.OntModelSpec;
import com.hp.hpl.jena.query.QueryExecution;
import com.hp.hpl.jena.query.QueryExecutionFactory;
import com.hp.hpl.jena.query.QueryFactory;
import com.hp.hpl.jena.query.ResultSet;
import com.hp.hpl.jena.query.ResultSetFormatter;
import com.hp.hpl.jena.rdf.model.ModelFactory;
public class OntoQuery{
    public static void main(String[] args) throws IOException{
//       创建一个本体模型,这里使用的是前一段时间设计的IIPO本体,附带实例。
        OntModel model = ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM);
        model.read("file:./IIPO.v1.1.with_individuals.owl");       
//      创建一个查询语句
        String queryString = "SELECT ?teacher ?student" +
        " WHERE " +
        "{ ?teacher <http://www.owl-ontologies.com/IIPO.owl#direct> ?student}";
//       创建一个查询
Query query = QueryFactory.create(queryString);
//      执行查询,获得结果
        QueryExecution qe = QueryExecutionFactory.create(query, model);
        ResultSet results = qe.execSelect();
//      向控制台输出结果s   
        ResultSetFormatter.out(System.out, results, query);
//      释放资源
        qe.close();
    } // the end of main.
} // the end.
返回的结果是:

| teacher                                           | student                                        |            
|====================================================================================================|
|<http://www.owl-ontologies.com/IIPO.owl#Teacher_1> | <http://www.owl-ontologies.com/IIPO.owl#Std_1> |


总结:并没能够很好的理解SPARQL,纯粹对Tutorial的翻译和rephrasing.

说明:文章中参考翻译的Tutorial http://jena.sourceforge.net/ARQ/Tutorial/index.html

引自:http://imarine.blog.163.com/blog/static/5138018320071119110889/

阅读更多
个人分类: ontology
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭