每当我开始使用 SQL 时,我倾向于在数据库中抛出一些探索性语句,以了解可用的内容以及数据的形式。
例如
show tables
describe table
select * from table
谁能帮助我了解使用 SPARQL 端点完成对 RDF 数据存储的类似探索的方法?
嗯,显而易见的第一个开始是查看数据中存在的类和属性。
以下是如何查看正在使用的类:
SELECT DISTINCT ?class
WHERE {
?s a ?class .
}
LIMIT 25
OFFSET 0
(LIMIT
并且OFFSET
在那里用于分页。值得习惯这些,特别是如果您通过 Internet 发送查询。我将在其他示例中省略它们。)
a
是一种特殊的 SPARQL(和Notation3 / Turtle)语法来表示rdf:type
谓词 - 它将单个实例链接到owl:Class
/rdfs:Class
类型(大致相当于 SQL RDBMS 中的表)。
其次,您要查看属性。您可以通过使用已搜索的类或仅查找属性来执行此操作。让我们从商店中取出所有属性:
SELECT DISTINCT ?property
WHERE {
?s ?property ?o .
}
这将获取您可能不感兴趣的所有属性。这相当于 SQL 中所有行列的列表,但没有按表进行任何分组。
更有用的是查看声明特定类的实例正在使用哪些属性:
SELECT DISTINCT ?property
WHERE {
?s a <http://xmlns.com/foaf/0.1/Person>;
?property ?o .
}
这将使您恢复在满足第一个三元组的任何实例上使用的属性 - 即具有rdf:type
of http://xmlns.com/foaf/0.1/Person
。
请记住,因为一个 rdf:Resource 可以有多个 rdf:type 属性——如果你愿意的话,可以是类——并且因为 RDF 的数据模型是可加的,所以你不会遇到菱形问题。类型只是另一种属性——它只是一个有用的社会协议,说有些东西是人、狗、基因或足球队。这并不意味着数据存储将包含通常与该类型关联的属性。该类型不保证资源可能具有的属性。
您需要熟悉数据模型以及 SPARQL 的 UNION 和 OPTIONAL 语法的使用。rdf:type 到 SQL 表的粗略映射就是这样 - 粗略的。
您可能想知道该属性指向的实体类型。首先,您可能想了解数据类型属性——相当于文字或原语。你知道,字符串、整数等。RDF 将这些文字定义为都继承自字符串。我们可以使用 SPARQL 过滤器方法过滤掉那些是文字的属性isLiteral
:
SELECT DISTINCT ?property
WHERE {
?s a <http://xmlns.com/foaf/0.1/Person>;
?property ?o .
FILTER isLiteral(?o)
}
我们在这里只获取以文字为对象的属性 - 字符串、日期时间、布尔值或其他 XSD 数据类型之一。
但是非文字对象呢?将这个非常简单的伪 Java 类定义视为一个类比:
public class Person {
int age;
Person marriedTo;
}
使用上面的查询,如果绑定了年龄属性,我们将返回表示年龄的文字。但是marriedTo 不是原始的(即RDF 术语中的文字)——它是对另一个对象的引用——在RDF/OWL 术语中,它是一个对象属性。但是我们不知道这些属性(谓词)引用了什么样的对象。此查询将为您提供附带类型(?o
值所属的类)的属性。
SELECT DISTINCT ?property, ?class
WHERE {
?s a <http://xmlns.com/foaf/0.1/Person>;
?property ?o .
?o a ?class .
FILTER(!isLiteral(?o))
}
这应该足以让自己定位到特定的数据集中。当然,我还建议您只提取一些单独的资源并检查它们。您可以使用 DESCRIBE 查询来做到这一点:
DESCRIBE <http://example.org/resource>
有一些 SPARQL 工具(例如SNORQL)可以让您在浏览器中执行此操作。我链接到的 SNORQL 实例有一个示例查询,用于探索可能的命名图,我在这里没有介绍。
如果您不熟悉 SPARQL,老实说,如果您遇到困难,最好的资源就是规范。这是一个 W3C 规范,但非常好(他们构建了一个不错的测试套件,因此您可以实际查看实现是否正确完成),如果您能克服复杂的语言,这将非常有帮助。
我发现以下一组探索性查询很有用:
看课:
select distinct ?type ?label
where {
?s a ?type .
OPTIONAL { ?type rdfs:label ?label }
}
看属性:
select distinct ?objprop ?label
where {
?objprop a owl:ObjectProperty .
OPTIONAL { ?objprop rdfs:label ?label }
}
查看数据属性:
select distinct ?dataprop ?label
where {
?dataprop a owl:DatatypeProperty .
OPTIONAL { ?dataprop rdfs:label ?label }
}
查看实际使用了哪些属性:
select distinct ?p ?label
where {
?s ?p ?o .
OPTIONAL { ?p rdfs:label ?label }
}
查看断言了哪些实体:
select distinct ?entity ?elabel ?type ?tlabel
where {
?entity a ?type .
OPTIONAL { ?entity rdfs:label ?elabel } .
OPTIONAL { ?type rdfs:label ?tlabel }
}
查看正在使用的不同图表:
select distinct ?g where {
graph ?g {
?s ?p ?o
}
}
SELECT DISTINCT * WHERE {
?s ?p ?o
}
LIMIT 10
我经常参考来自 voiD 项目的查询列表。它们主要具有统计性质,但不仅如此。从某些语句中删除 COUNT 以获得实际值应该不难。
尤其是对于大型数据集,重要的是要区分模式和噪声,并了解哪些结构被大量使用,哪些结构很少。而不是SELECT DISTINCT
,我使用聚合查询来计算主要类、谓词等。例如,以下是如何查看数据集中最重要的谓词:
SELECT ?pred (COUNT(*) as ?triples)
WHERE {
?s ?pred ?o .
}
GROUP BY ?pred
ORDER BY DESC(?triples)
LIMIT 100
我通常首先列出存储库中的图及其大小,然后查看感兴趣的图中的类(再次使用计数) ,然后查看我感兴趣的类的谓词等。
当然,如果合适的话,这些选择器可以组合和限制。要查看为 type 的实例定义了哪些谓词foaf:Person
,并按图将其分解,您可以使用以下命令:
SELECT ?g ?pred (COUNT(*) as ?triples)
WHERE {
GRAPH ?g {
?s a foaf:Person .
?s ?pred ?o .
}
GROUP BY ?g ?pred
ORDER BY ?g DESC(?triples)
这将按频率降序列出每个图表及其中的谓词。