3. SPARQL 查询入门:SELECT 语句与基本模式匹配
好,我们终于开始写真正的查询了。前面两章把 RDF 和 SPARQL 的背景铺了一遍,可能你觉得有点虚。这一章我们直接上手,用 SELECT 语句从药物图谱里把数据“拽”出来。
SELECT 是 SPARQL 里最常用的查询形式。说白了,它有点像 SQL 里的 SELECT,但又不完全一样。核心区别在于——SPARQL 查的是图,不是表。你想想看,图数据没有固定的列,你得用“三元组模式”去描述你要找的东西长什么样。
3.1 SELECT 语句的基本骨架
一个最简单的 SELECT 查询长这样:
SELECT ?药物 ?靶点
WHERE {
?药物 rdf:type <http://example.org/drug> .
?药物 <http://example.org/target> ?靶点 .
}
嗯,来拆解一下。
- SELECT 子句:列出你关心的变量。变量用问号开头,比如
?药物、?靶点。 - WHERE 子句:里面放一组三元组模式。这些模式就是你要在图里匹配的“路标”。
- 三元组模式:主语、谓语、宾语。每个位置可以是具体 URI、字面量,也可以是变量。
?a、?b。虽然 SPARQL 不限制,但几个月后回头看,你大概率会忘记 ?x 到底代表什么东西。
3.2 基本模式匹配的工作原理
SPARQL 引擎是怎么工作的?它会把 WHERE 里的每个三元组模式,拿到 RDF 图里去做子图匹配。
举个例子。假设药物图谱里有这么几条数据:
<http://example.org/drug/阿司匹林> rdf:type <http://example.org/drug> .
<http://example.org/drug/阿司匹林> <http://example.org/target> <http://example.org/protein/COX-1> .
<http://example.org/drug/阿司匹林> <http://example.org/target> <http://example.org/protein/COX-2> .
当你运行上面的 SELECT 查询时,引擎会做三件事:
- 找到所有类型是
drug的节点——这里匹配到“阿司匹林”。 - 对每个 drug 节点,找到它的
target属性值——这里找到 COX-1 和 COX-2。 - 把匹配到的变量值组合成结果行。
结果就是两行:
?药物 ?靶点
阿司匹林 COX-1
阿司匹林 COX-2
3.3 避坑:前缀声明的重要性
你肯定不想每次写 URI 都写全长。太痛苦了。SPARQL 提供了 PREFIX 关键字。我记得刚开始写查询时,总是忘记加前缀声明,结果查了半天什么也没返回……
PREFIX d: <http://example.org/drug/>
PREFIX p: <http://example.org/protein/>
PREFIX vocab: <http://example.org/>
SELECT ?药物 ?靶点
WHERE {
?药物 rdf:type vocab:drug .
?药物 vocab:target ?靶点 .
}
这里我定义了三个前缀:d: 用于药物,p: 用于蛋白,vocab: 用于命名空间。注意,rdf:type 是 SPARQL 内置前缀 rdf:,不用自己声明。
PREFIX d:<http://...> 是错的,必须写成 PREFIX d: <http://...>。这个空格很容易被忽略,但丢了 SPARQL 解析器会报错。
另外,前缀只是别名,不会改变查询语义。引擎在内部会把前缀展开成完整 URI。
3.4 使用 FILTER 缩小结果范围
大部分时候你不需要所有数据。你想查“靶点是 COX-1 的药物有哪些?”这时就要用 FILTER。
PREFIX vocab: <http://example.org/>
SELECT ?药物
WHERE {
?药物 rdf:type vocab:drug .
?药物 vocab:target ?靶点 .
FILTER(?靶点 = <http://example.org/protein/COX-1>)
}
FILTER 里可以写各种条件:
- 字符串比较:
FILTER(CONTAINS(?药物名称, "阿司匹林")) - 数值比较:
FILTER(?分子量 > 300) - 逻辑组合:
FILTER(?a > 10 && ?b < 20)
你想想看,没有 FILTER 的话,你只能返回所有数据,然后在应用层过滤——效率太低了。数据量一上来,网络传输就是瓶颈。
3.5 本章知识结构
下面的 SVG 把 SELECT 查询的核心流程画出来了。从“发现目标”到“写出三元组模式”,再到“添加过滤条件”,最后“获取结果”。
3.6 常见新手问题
| 问题 | 原因 | 解决方法 |
|---|---|---|
| 查询返回空结果 | URI 写错或前缀未声明 | 检查前缀声明和 URI 是否与数据一致 |
| 变量名拼写不一致 | WHERE 里用了 ?protein,SELECT 里写了 ?protien |
养成复制变量名的习惯 |
| 忘记加 . 号 | 每个三元组模式必须以 . 结束(最后一个可选) | 写模式时统一加 . 号 |
嗯,这一章的内容先到这里。SELECT 和基本模式匹配是 SPARQL 的基石。后面的 JOIN、OPTIONAL、UNION 都是在这一层基础上叠加的。把这几步练熟,后面的路就好走了。