SPARQL/基础
SPARQL 看起来可能很复杂,但简单基础已经可以让你走很远 - 如果你愿意,你可以在本章之后停止阅读,你已经知道足够编写许多有趣的查询。其他章节只是添加了更多主题的信息,你可以用它们来编写不同的查询。它们中的每一个都将使你能够编写更棒的查询,但它们都不是必需的 - 你可以随时停止阅读,并希望仍然能获得大量有用的知识!
此外,如果你以前从未听说过维基数据、SPARQL 或 WDQS,这里简要解释一下这些术语。
- 维基数据是一个知识数据库。它包含很多语句,例如“加拿大的首都为渥太华”或“蒙娜丽莎是油画在杨木板上”或“金的热导率为 25.418 焦耳每摩尔开尔文”。
- SPARQL 是一种用于知识数据库的提问(查询)语言。使用正确的数据库,SPARQL 查询可以回答诸如“音乐中最流行的调性是什么?”或“哪个角色由最多演员扮演?”或“血型的分布情况如何?”或“今年有哪些作家的作品进入公有领域?”。
- WDQS,即 维基数据查询服务,将两者结合在一起:你输入 SPARQL 查询,它在维基数据的数据库上运行查询并显示结果。
一个简单的 SPARQL 查询如下所示
SELECT ?a ?b ?c
WHERE
{
x y ?a.
m n ?b.
?b f ?c.
}
SELECT
子句列出了你想要返回的变量(变量以问号开头),而 WHERE
子句包含对它们的限制,主要是三元组的形式。维基数据(以及类似的知识数据库)中的所有信息都以三元组的形式存储;当你运行查询时,查询服务会尝试用实际值填充变量,以便生成的元组出现在知识数据库中,并为它找到的每个变量组合返回一个结果。
三元组可以像句子一样阅读(这就是它以句号结尾的原因),包含一个主语、一个谓语和一个宾语
SELECT ?fruit
WHERE
{
?fruit hasColor yellow.
?fruit tastes sour.
}
此查询的结果可能包括,例如,“柠檬”。在维基数据中,大多数属性是“有”-类型的属性,因此查询可以改写为
SELECT ?fruit
WHERE
{
?fruit color yellow.
?fruit taste sour.
}
读起来就像“?fruit
有颜色‘黄色’”(不是“?fruit
是‘黄色’的颜色” - 请记住这对“父母”/“孩子”之类的属性!)。
但是,这不是 WDQS 的好例子。味道是主观的,所以维基数据没有关于它的属性。相反,让我们考虑一下父母/孩子关系,它们大多是明确的。
假设我们想要列出巴洛克作曲家约翰·塞巴斯蒂安·巴赫的所有孩子。使用上面的查询中的伪元素,你将如何编写该查询?
希望你得到类似这样的东西
SELECT ?child
WHERE
{
# either this...
?child parent Bach.
# or this...
?child father Bach.
# or this.
Bach child ?child.
# (note: everything after a ‘#’ is a comment and ignored by WDQS.)
}
前两个三元组表示 ?child
必须有父母/父亲巴赫;第三个表示巴赫必须有孩子 ?child
。让我们暂时使用第二个。
那么要把它变成一个真正的 WDQS 查询,还需要做什么呢?在维基数据中,项目和属性不是由人类可读的名称来标识的,比如“父亲”(属性)或“巴赫”(项目)。(有充分的理由:“约翰·塞巴斯蒂安·巴赫”也是一位 德国画家 的名字,而“巴赫”也可能指 姓氏、 法国公社、 水星陨石坑 等等)。相反,维基数据项目和属性被分配了一个标识符。要查找项目的标识符,我们 搜索 项目并复制看起来像是我们正在寻找的项目的 Q 号码(例如,基于描述)。要查找属性的标识符,我们执行相同的操作,但搜索“P:搜索词”而不是仅仅是“搜索词”,这将搜索限制为属性。这告诉我们,著名的作曲家约翰·塞巴斯蒂安·巴赫是 Q1339,而指定项目父亲的属性是 P22。
最后但同样重要的是,我们需要包含前缀。对于简单的 WDQS 三元组,项目应该以 wd:
为前缀,属性应该以 wdt:
为前缀。(但这仅适用于固定值 - 变量没有前缀!)。
将这些放在一起,我们得到了第一个真正的 WDQS 查询
SELECT ?child
WHERE
{
# ?child father Bach
?child wdt:P22 wd:Q1339.
}
点击“试试吧”链接,然后在 WDQS 页面上“运行”查询。你得到了什么?
child |
---|
wd:Q57225 |
wd:Q76428 |
… |
好吧,这令人失望。你只看到标识符。你可以点击它们查看它们的维基数据页面(包括人类可读的标签),但有没有更好的方法来查看结果呢?
好吧,事实证明,有! (反问句真是太好了!)。如果你在 WHERE
子句中包含魔法文本
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". }
你会得到额外的变量:对于查询中的每个变量 ?foo
,你现在还有一个变量 ?fooLabel
,它包含 ?foo
背后的项目的标签。如果你将它添加到 SELECT
子句中,你将得到项目及其标签
SELECT ?child ?childLabel
WHERE
{
# ?child father Bach
?child wdt:P22 wd:Q1339.
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". }
}
尝试运行该查询 - 你应该不仅看到项目编号,而且还看到各种孩子的姓名。
child | childLabel |
---|---|
wd:Q57225 | 约翰·克里斯托弗·弗里德里希·巴赫 |
wd:Q76428 | 卡尔·菲利普·埃曼努埃尔·巴赫 |
… | … |
这完成了基础知识。尝试通过改变属性来修改它。