前言

看这篇文章之前,如果对RDF了解不够可以先看我的这篇文章,对RDF及其序列化方法进行了详细介绍。本篇文章是对瞿裕忠老师的《语义网技术体系》部分章节的学习笔记。

RDF是W3C推荐的数据存储方式,现实世界中的数据量是巨大的,将RDF图序列化后,对这些RDF文档的存储是一个问题,同时,如果要从这些文档中找到自己想要的信息,就需要一个便于使用的查询语言,那就是SPARQL。

对于RDF数据库和SPARQL的理解可以参照传统关系型数据库。例如:小明是五年级二班的学生,今年8岁。这样一个信息,

用传统关系数据库表示为:

姓名 年级 班级 年龄
小明 五年级 二班 8

用RDF序列化之后为:

可见,对于同样的信息,传统关系型数据库采用图表的方式存储,RDF文档使用RDF图的形式存储;进一步的,传统关系型数据库采用SQL查询数据库中的数据,而对于RDF文档构成的数据库,使用SPARQL查询语言。值得一提的是,SPARQL本身并不只是一个查询语言,它是定义在RDF数据库或者Web上查询和操纵RDF数据的一组语言和协议,而SPARQL查询语言是其中的核心。

文章目录

  • 1. SPARQL的基本图模式
    • 1.1 三元组模式
    • 1.2 基本图模式示例
  • 2. SPARQL查询语言常用语法
    • 2.1 SPARQL常用关键字
      • 1) 基本图模式
      • 2) 图模式的组合
      • 3) 属性路径
      • 4) 结果的组织
      • 5) 数据集的选取
      • 6) 其他查询形式
    • 2.2 SPARQL代码示例
      • 例1. 最简单的查询
      • 例2. FILTER过滤器
      • 例3. NOT EXISTS
      • 例4. 图模式合并
      • 例5. OPTIONAL
      • 例6. UNION
      • 例7. 符号 ‘\’
      • 例8. 符号 ‘|’
      • 例9. 符号 ‘^’
      • 例10. ORDER BY & ASC & DESC
      • 例11. DISTINCT
      • 例12. LIMIT & OFFSET
      • 例13. FROM & FROM NAMED & GRAPH
      • 例14. ASK & CONSTRUCT & DESCRIBE
  • 3. 在Python中使用SPARQL语言
    • 3.1 rdflib 简要介绍
    • 3.2 创建RDF文档
    • 3.3 SPARQL查询RDF文档
    • 3.4 g.bind()使用举例

1. SPARQL的基本图模式

SPARQL查询基于的是图模式的匹配。图模式是SPARQL中的核心概念,基本图模式是SPARQL最简单的图模式。

1.1 三元组模式

一个基本图模式就是一个三元组模式的集合,这对应到RDF中即是,一个RDF图是一个RDF三元组的集合。显然,二者在形式上非常类似,三元组模式也是由主语、谓语和宾语组成,唯一的不同是,三元组模式中的主语和宾语还可以是变量。在SPARQL中,变量以问号(?)或者($)美元符号开头,例如:?x, ?name。

在一个基本图模式中,三元组模式通常通过共有变量连接起来,也就是说,基本图模式表示成的有向图一般是连通的。

1.2 基本图模式示例

以下将分别用图示和代码说明基本图模式。

图示

图中 ?x 和 ?y 是两个变量,通过图(b)查询的图模式在图(a)所示的待查数据中匹配,得到了变量 ?x 和 ?y 的值。

代码

SELECT ?name ?mbox
WHERE{?x foaf:name ?name.?x foaf:mbox ?mbox}

如代码中所示,花括号及其之间的部分是由2个三元组模式组成的基本图模式(为了简化,所有URI的前缀定义都被省略)

2. SPARQL查询语言常用语法

学习语法,千言万语不如一个代码示例来的清晰,下面我首先列出SPARQL常用的关键字及其介绍,然后分类给出代码示例。

2.1 SPARQL常用关键字

1) 基本图模式

关键字 介绍
SELECT 指出需要在结果中提供其绑定的变量
WHERE 指出需要去匹配的图模式
FILTER 引导一个过滤器,实质上是一个布尔函数,当返回值为真时,相应结果才会被返回

2) 图模式的组合

关键字 介绍
OPTIONAL 意味着并不强制要求这个图模式必须被匹配,当这个图模式不能匹配时,并不会因此去除整条结果
UNION 其连接的图模式并不要求被同时匹配,只要其中一个被匹配便可返回结果
NOT EXISTS 与FILTER连用,当不存在指定的图模式时返回true

3) 属性路径

关键字 介绍
/ 分隔路径属性,用于当只有路径的首尾顶点显示在查询中时
| 连接可以互相替代的两个属性
^ 用来表示路径中的一个反向的属性
! 表示否定
?、+、* 属性路径

4) 结果的组织

关键字 介绍
ORDER BY 对查询结果按照指定的变量进行排序
ASC 升序排序
DESC 降序排序
DISTINCT 消除重复的查询结果
LIMIT 限制返回的结果条数
OFFSET 跳过固定条数的结果
GROUP BY 对查询结果分组
HAVING 分组过滤
COUNT 计数
SUM 求和
AVG 求平均

5) 数据集的选取

关键字 介绍
FROM 重新指定缺省图
FROM NAMED 指定具名图
GRAPH 使用具名图

6) 其他查询形式

关键字 介绍
ASK 不关心变量绑定的结果,而是关心一个查询图模式是否至少能找到一种匹配,找的到则返回True
CONSTRUCT 基于查询的结果构造一个新的RDF图
DESCRIBE 获取关于一个特定URI标识的资源的所有RDF数据

2.2 SPARQL代码示例

例1. 最简单的查询


基本图模式查询可以视作三元组模式查询的合取查询。

例2. FILTER过滤器


如果要求某个变量必须绑定到字符串类型的字面量,并且与指定的正则表达式相匹配,可以使用regex。这里的regex(?title, “^电子商务”)是用来判断变量 ?title 是否绑定到一个字符串类型的字面量,并且该字面量的词汇形式以“电子商务”作为前缀。

例3. NOT EXISTS


将一个图模式是否能够找到匹配来作为另一个图模式中的过滤器。

例4. 图模式合并


以上两段代码的结果是完全相同的,简单的给出多个图模式意味着他们的合取,即相当于将这些图模式合并。

例5. OPTIONAL


如果OPRIONAL关键字后的模式没有得到匹配,仍然不会因此去除整条结果。

例6. UNION


只要UNION连接的两个模式中有一个得到了匹配,则返回结果

例7. 符号 ‘\’


图中两段代码是等价的,当我只关心路径的起点和终点的时候,就可以直接这样写,忽略其中间节点,在这里就是 ?y。

例8. 符号 ‘|’


以上两段代码是等价的,可以看到 ‘|’ 也就类似于逻辑语言中的“或”。

例9. 符号 ‘^’


上面两段代码是等价的,‘^’ 表示一个反向的属性。

例10. ORDER BY & ASC & DESC


这段代码的结果将会依照 ?name 升序排列。

例11. DISTINCT


第一段代码的结果中可能会有重复的结果,第二段代码加入了DISTINCT关键字,其结果将各不相同,不会有重复。

例12. LIMIT & OFFSET


这段代码的结果将会直接跳过前10条结果,然后返回从第11条开始的不超过20条结果。

例13. FROM & FROM NAMED & GRAPH


查询总是在一个数据集上执行的,它由多个RDF图组成,包括一个缺省图和多个具名图。在不做任何指定的情况下,查询总是在缺省图上进行。对于一个具体的本地RDF数据库或者网络上的SPARQL端口而言,缺省图通常是预先设定好的,因此在查询中就不必再显示指定。缺省图的指定通过关键字FROM实现。以上的代码中,将缺省图重新指定。


当我们指定多个缺省图时,缺省图将是这多个图的合并。


FROM NAMED关键字可以指定具名图,指定具名图的意义在于可以将一部分图模式放在缺省图以外的RDF图上去匹配,而对于具名图的使用要借助GRAPH关键字。在以上的代码中,第一个图模式会在缺省图中匹配,而第二个图模式会在GRAPH关键字指出的具名图中匹配。

有时候我们需要知道某个模式到底在哪个RDF图中可以得到匹配。如以上代码所示,GRAPH后的图模式将会在声明出的所有具名图中一一匹配,如果再某个具名图中模式得到了匹配,则这个具名图的URI将会被绑定到变量 ?g 上。通过这样一种方式,查询者不但不需要知道具体应该在哪个具名图中查询,而且还可以得知可以在哪个具名图中查到结果。

例14. ASK & CONSTRUCT & DESCRIBE


如果图模式得到匹配,ASK将会返回True,否则返回False。

如代码所示,CONSTRUCT和WHERE各引导了一个图模式,这两个图模式共享变量,其中,CONSTRUCT引导的图模式也叫做图模板,输出的结果将会依照这个图模板,然后使用从WHERE引导的图模式匹配的变量,进而生成新的RDF图。

这条查询将返回描述 http://ws.nju.edu.cn/people/gcheng 这个URI表示的资源的全部RDF数据。

这条查询出了返回 http://ws.nju.edu.cn/people/gcheng 标识资源的 RDF 数据之外,还将匹配关键字 WHERE 引出的图模式,并对于绑定到变量 ?x 和 ?y 的每个资源(其标识可以是URI,也可以是空白节点),也会获取其RDF数据,最终将所有这些 RDF 数据合并返回。

3. 在Python中使用SPARQL语言

学习任何一门语言切忌纸上谈兵,学到了就要使用,对于SPARQL语言的使用以及RDF文档的创建,大多使用程序实现,我们基本不会去手动写RDF文档,同时我们的SPARQL查询语句也常常嵌套在工程代码之中。在这里我介绍如何利用Python实现RDF文件的创建及查询,这里的文件可能在本地也可能在远端。

在Python中实现SPARQL语言操作需要借助Python库rdflib,这里结合例子讲一些常用用法。

3.1 rdflib 简要介绍

 from rdflib import Graph, Literal, RDF, OWL, RDFS, URIRef, Namespacefrom rdflib.namespace import FOAF , XSD

以上列出的就是常用的rdflib功能,其中Graph是最重要的一类,以下通过表格简单介绍,然后结合后面例子中的注释就可以知道详细用法。

名称 功能
Literal 创建字面量
URIRef 创建URI资源链接
Namespace 声明命名空间并取别名
OWL, RDF, RDFS, FOAF, XSD 命名空间
Graph函数 功能
g=Graph() 声明一个对象
g.add() 向RDF图中添加三元组
g.parse() 解析RDF文件,有属性format可以指定文件格式
g.remove() 移除三元组
g.bind() 绑定命名空间到一个更易读的字符串,如FOAF到"foaf",在输出中生效,使输出更加易读
g.serialize() 将RDF图序列化并存储,有属性format指定存储的RDF文档格式
g.triples 模糊匹配,参数是一个三元组,通过对三元组中的某一个或两个赋值为None,从而实现模糊匹配

3.2 创建RDF文档

from rdflib import Graph, FOAF, Namespace, URIRef, Literal#创建RDF图对象
g = Graph()#声明命名空间
authors = Namespace("http://www.book.org/authors#")#添加节点
a = URIRef(authors["a"])
b = URIRef(authors["b"])
c = URIRef(authors["c"])#添加三元组
g.add((a,FOAF.name,Literal("Yuzhong Qu")))
g.add((a,FOAF.mbox,Literal("<mailto:yzqu@nju.edu.cn>")))
g.add((b,FOAF.name,Literal("Wei Hu")))
g.add((b,FOAF.mbox,Literal("<mailto:whu@nju.edu.cn>")))
g.add((c,FOAF.mbox,Literal("<mailto:gcheng@nju.edu.cn>")))#序列化生成的RDF图并存储,第一个参数是存储地址,根据自己实际情况改写
#这里的serialize如果不加地址直接放在print函数里输出,会输出整个序列化后的RDF文档
g.serialize("./SPARQL/data/rdf1.ttl",format="turtle")
print("Already Stored!")

生成的RDF文档如下:

3.3 SPARQL查询RDF文档

from unittest import result
from rdflib import Namespace, FOAF, URIRef, Literal, Graph
import numpy as np#创建RDF图对象
g = Graph()#加载待查询的RDF文档
g.parse("./SPARQL/data/rdf1.ttl",format="turtle")#格式一:在一行显示查询语句,不可跨行
# q = "SELECT ?name ?mbox WHERE { ?x foaf:name ?name. ?x foaf:mbox ?mbox}"#格式二:多行显示查询语句,格式清晰
q = """SELECT ?name ?mboxWHERE { ?x foaf:name ?name.?x foaf:mbox ?mbox}"""
#查询
result = g.query(q)#获取查询结果的方式一
# result_np = np.asarray(list(result))
# for v in result_np:
#     print(v)#获取查询结果的方式二
for row in result:print(f"{row.name} have {row.mbox}")

查询之后以方式一输出结果如下:

查询之后以方式二输出结果如下:

query函数的返回值是什么?
从官方文档看到,query函数的返回值根据查询类型的不同有三种情况:
select: 返回查询结果的行组成的一个对象
ask:返回一个bool值
constructdescribe:根据情况返回三元组构成的图
我们这里主要讨论常用的select,对于query的返回值在官方文档里已经说的很清楚了,我们关注的是对返回值的利用,方式有两种,对应代码中的方式一和方式二:
a) 先将结果转化为Python的list,然后将list转化为numpy的数组,然后进行操作。在讲结果转化为list之后,就可以想象此时的结果是一个二维数组。
b) 通过我们在查询时使用的变量名,对于返回的每一行结果可以直接查询相应的匹配。

3.4 g.bind()使用举例

  • 不使用g.bind()
 from rdflib import Graph, FOAF, Namespace, URIRef, Literal#创建RDF图对象g = Graph()#声明命名空间authors = Namespace("http://www.book.org/authors#")ns = Namespace("http://www.ns.org/authors#")#g.bind("foaf",FOAF)#g.bind("ns",ns)#添加节点a = URIRef(authors["a"])b = URIRef(authors["b"])#添加三元组g.add((a,FOAF.name,Literal("Yuzhong Qu")))g.add((b,ns.name,Literal("Wei Hu")))#序列化生成的RDF图并存储g.serialize("./data/rdf3.ttl",format="turtle")print("Already Stored!")

生成的RDF文档如下:

  • 使用g.bind()
 from rdflib import Graph, FOAF, Namespace, URIRef, Literal#创建RDF图对象g = Graph()#声明命名空间authors = Namespace("http://www.book.org/authors#")ns = Namespace("http://www.ns.org/authors#")g.bind("foaf",FOAF)g.bind("ns",ns)#添加节点a = URIRef(authors["a"])b = URIRef(authors["b"])#添加三元组g.add((a,FOAF.name,Literal("Yuzhong Qu")))g.add((b,ns.name,Literal("Wei Hu")))#序列化生成的RDF图并存储g.serialize("./data/rdf3.ttl",format="turtle")print("Already Stored!")

生成的RDF文档如下:

显然,当使用g.bind()时,生成的RDF文档的可读性会高很多。

SPARQL查询语言概念及语法相关推荐

  1. C++ 基础概念、语法和易错点整理

    目录 基础知识 构造函数与析构函数 虚函数 继承 单例模式 重载.隐藏和重写(覆盖) vector 扩容机制应注意的问题 STL 迭代器 前言 快秋招了,专门用一篇博客整理一下 C++ 的一些基础概念 ...

  2. JavaScript从入门到精通之入门篇(一)概念与语法

    入门篇大纲 第一部分 概念与语法 1.JavaScript的历史 2.基本概念 3.JavaScript的使用.调试和异常处理 4.基本词法和变量 5.数据类型和类型转换 6.运算符 算数运算符 赋值 ...

  3. Java中抽象类和接口在概念、语法和应用上的区别和关系

    2019独角兽企业重金招聘Python工程师标准>>> 春招开始了,盆友们都忙着准备笔试.准备面试,复习学过的知识点,当然我也不例外,在这里祝每一个"有心人"心想 ...

  4. YAML第一章 基本概念及语法

    YAML第一章 基本概念及语法 简介 本文对YAML的基本概念及语法进行了详细的分析,尤其是对YAML的语法进行了详细的阐述,旨在希望通过本文能对YAML有一个基本的了解,能够书写YAML文档. 声明 ...

  5. 第八章第一节:Java继承之继承概念、语法、成员访问和super关键字

    文章目录 一:继承的概念及语法 (1)什么是继承 (2)Java继承语法 二:成员访问 (1)子类访问父类的成员变量 (2)子类访问父类的成员方法 三:super关键字 (1)super关键字 A:作 ...

  6. MDX基本概念和语法

    MDX基本概念和语法 1 MDX简介 1.1 MDX重要概念 1.2 维度(Dimensions).级别(Levels).成员(Members)和度量值(Measures) 1.3 轴维度和切片器维度 ...

  7. python(三):概念、语法、数据类型

    文章目录 基本概念 基本语法 数据类型 1.数值 2.字符串 字符串介绍 格式化字符串 复制字符串 3.布尔值和空值 4.类型检查 5.对象 对象(object)介绍 对象的结构 变量和对象 6.类型 ...

  8. SQL Server存储过程的基本概念以及语法【转】

    存储过程的概念        SQL Server提供了一种方法,它可以将一些固定的操作集中起来由SQL Server数据库服务器来完成,以实现某个任务,这种方法就是存储过程.        存储过程 ...

  9. c/c++入门教程 - 2.4.6 继承、公共继承、保护继承、私有继承、virtual虚继承(概念、语法、方式、构造和析构顺序、同名成员处理、继承同名静态成员处理、多继承语法、菱形继承、钻石继承)

    目录 4.6 继承 4.6.1 继承的基本语法 4.6.2 继承方式 4.6.3 继承中的对象模型 4.6.4 继承中构造和析构顺序 4.6.5 继承同名成员处理方式 4.6.6 继承同名静态成员处理 ...

最新文章

  1. 算法总结---最常用的五大算法(算法题思路)
  2. HarmonyOS之数据管理·分布式数据服务的应用
  3. 防火墙(5)——五表
  4. 红米ac2100breed看模块_骁龙865加持,红米K30S至尊纪念版11日再开售
  5. vue 调用webservice_js跨域调用WebService的简单实例
  6. 脚手架-- yarn link后,Error: Cannot find module 。。。
  7. extjs string类型转date_extjs 处理Object格式的Date对象
  8. ubuntu 下更新pip后发生 ImportError: cannot import name 'main'的问题解决
  9. 关于在for循环中绑定事件打印变量i是最后一次。
  10. 2013台式计算机,显卡天梯图 2013最新台式机显卡天梯图
  11. 控制直流电机正反转以及刹车电路设计
  12. 曲面映射的算法理论基础
  13. 使用C#存储数据时excel有Microsoft切换到了wps时的引用
  14. 图像处理之双线性插值法
  15. PLC PID调试总结
  16. 谷歌浏览器设置启动页被hao123劫持_win10系统打开chrome会被hao123劫持怎么办?解决方案...
  17. java算法优化_Java学习笔记---Java简单的代码算法优化(例)
  18. 使用 parted 对单个磁盘进行分区并进行配额
  19. java毕设_城市公交系统
  20. 车辆的纵向控制之标定

热门文章

  1. ArcGIS空间分析实验教程-部分实验案例(ArcPy实现)
  2. 2019年 第11届 全国大学生数学竞赛 初赛(非数学类)试题详细解答
  3. OMNI.COM The Greatest program in the world
  4. sql 中or与in的查询效率对比
  5. 微信公众号商城是否需要云服务器,云商城公众号绑定、微信支付配置文档
  6. java后端获取支付宝会员的基本信息
  7. 手电筒安卓_安利一款演唱会必备APP——随手电筒
  8. 手把手写C++服务器(7):给C语言程序员看的C++科普
  9. cython_bbox库就该这么安装
  10. socket listen函数