面向RDF的三元组数据库
由于 RDF 是 W3C 推荐的表示语义网上关联数据(Linked Data)的标准格式,RDF也是 表示和发布 Web上知识图谱的最主要数据格式之一。 面向 RDF的三元组数据库是专门为存储大规模 RDF 数据而开发的知识图谱数据库,其支 持 RDF 的标准查询语言SPARQL。主要包括开源和商业RDF三元组数据库。
RDF格式存储——Apache Jena
开源数据库 – Apache Jena,是一个免费开源的支 持构建语义网络和 数据链接应用的 Java 框架 下载地址:http://jena.apache.org/download/index.cgi 我下载的是apache-jena-fuseki-4.1.0.zip (SHA512, PGP)
同样需要在环境变量中添加路径,然后打开命令行,进入你的fuseki所在路径,如果这个路径不在C盘的话需要输入
> D:
按回车,就好了
进入所在目录后,输入fuseki-server,启动服务 这里需要注意,fuseki需要安装jdk11,下载地址: https://www.oracle.com/java/technologies/javase-jdk11-downloads.html
在oracle官网下载Java SE 11需要注册,如果嫌麻烦的话可以点击这里下载
启动成功后,在浏览器输入localhost:3030,即可进入apache jena fuseki,初次进入效果如图:
fuseki 应用
首先定义音乐知识图谱如下: 图中所有内容(主语、宾语、关系)都可以用一个足够长的字符串去唯一识别定义。 前缀需要,但是不一定存在,因此将前缀统一以以下方式表达:
PREFIX m: http://kg.course/music/
在这里我们用前缀描述,可以使我们的数据变为唯一的。 根据上图,使用python脚本生成1000个音乐知识图谱的三元组:
<http://kg.course/music/album_0025> <http://kg.course/music/album_name> "album_name_0025" .
<http://kg.course/music/track_00001> <http://kg.course/music/track_album> <http://kg.course/music/album_0001> .
<http://kg.course/music/track_00001> <http://kg.course/music/track_artist> <http://kg.course/music/artist_001> .
<http://kg.course/music/track_00001> <http://kg.course/music/track_name> "track_name_00001" .
<http://kg.course/music/track_00001> <http://kg.course/music/track_tag> "tag_name_01" .
<http://kg.course/music/track_00002> <http://kg.course/music/track_album> <http://kg.course/music/album_0003> .
<http://kg.course/music/track_00002> <http://kg.course/music/track_artist> <http://kg.course/music/artist_002> .
<http://kg.course/music/track_00002> <http://kg.course/music/track_name> "track_name_00002" .
<http://kg.course/music/track_00002> <http://kg.course/music/track_tag> "tag_name_01" .
<http://kg.course/music/track_00003> <http://kg.course/music/track_album> <http://kg.course/music/album_0001> .
<http://kg.course/music/track_00003> <http://kg.course/music/track_artist> <http://kg.course/music/artist_003> .
在数据中,http://kg.course/music/是我们的前缀,music是我们的图谱名称 其中的第一列,为我们的名称;第二列是属性名;第三列是该名称对应的值。即三元组中的主谓宾。
代码如下:
#!/usr/bin/env python
# coding: utf-8
import random
import sys
track_name = "<http://kg.course/music/track_%05d> <http://kg.course/music/track_name> \"track_name_%05d\" ."
track_album = "<http://kg.course/music/track_%05d> <http://kg.course/music/track_album> <http://kg.course/music/album_%04d> ."
album_name = "<http://kg.course/music/album_%04d> <http://kg.course/music/album_name> \"album_name_%04d\" ."
track_artist = "<http://kg.course/music/track_%05d> <http://kg.course/music/track_artist> <http://kg.course/music/artist_%03d> ."
artist_name = "<http://kg.course/music/artist_%03d> <http://kg.course/music/artist_name> \"artist_name_%03d\" ."
tag_name = "<http://kg.course/music/track_%05d> <http://kg.course/music/track_tag> \"tag_name_%02d\" ."
total_sum = 1000
triples_sum = 0
triples = set()
if len(sys.argv) >= 2:
print('sys.argv = ', sys.argv)
try:
total_sum = int(sys.argv[1])
except:
total_sum = 1000
for i in range(1, total_sum):
track_str = track_name % (i, i)
s = random.randint(1, 10)
album_str = track_album % (i, i/s + 1)
album_name_str = album_name % (i/10 + 1, i/10 + 1)
t = random.randint(1, 100)
track_artist_str = track_artist % (i, i % t)
artist_name_str = artist_name % (i % t, i % t)
k = random.randint(1, 10)
tag_name_str = tag_name % (i, i % k + 1)
triples.add(track_str)
if total_sum <= len(triples):
break
triples.add(album_str)
if total_sum <= len(triples):
break
triples.add(album_name_str)
if total_sum <= len(triples):
break
triples.add(track_artist_str)
if total_sum <= len(triples):
break
"""
triples.append(artist_name_str)
triples_sum += 1
if total_sum <= triples_sum:
break
"""
triples.add(tag_name_str)
if total_sum <= len(triples):
break
triples = list(triples)
triples.sort()
filename = "music_%d_triples.nt" % total_sum
with open(filename, "w+") as f:
f.write("\n".join(triples))
运行以上脚本,会生成一个.nt类型的文件,下面我们就用这个生成的数据来进行操作。
在前面的打开fuseki服务,打开浏览器,输入http://localhost:3030/,进入fuseki界面 点击页面上方的manage datasets,如果过去有数据的话,会在existing datasets内显示 点击add new dataset,输入数据名称,在数据类型这里选择第二项(第一项意思是关掉fuseki后数据会丢失,第二项意思是数据会永久保留),然后点击创建,如上图,我创建了一个music数据。 点击update data,选择刚刚生成的nt文件,点击update all或update now上传文件(注意这里必须点了update数据才会上传)。 完成后点击info即可查看我们上传的数据。
接下来,点击query就可以对数据进行一些简单的操作了。 点击selection of triples,会自动生成一组查询语句,查询任意满足主谓宾的语句(也就是刚刚生成的所有三元组数据) 运行结果如下,Table中显示的是查询结果,Raw Response显示的json格式的字典,也可以对数据进行下载,会生成一个.csv文件。 还可以有一些具体的查询语句
1.查询某一艺术家的所有歌曲
PREFIX music: <http://kg.course/music/>
SELECT DISTINCT ?trackID
WHERE {
?trackID music:track_artist music:artist_001
}
上述代码中,第一行用music表示了后面的前缀内容,然后我们需要列出所有不同的值,这些值满足:属性music:track_artist这一项,他的值是music:artist_001,即查找出所有artist_001的歌曲,这里的trackID,是生成数据后的数据名称。
其余查询语句如下:
2.查询某一艺术家的所有歌曲的歌曲名
PREFIX music: <http://kg.course/music/>
SELECT ?name
WHERE {
?trackID music:track_artist music:artist_001 .
?trackID music:track_name ?name
}
3.查询某一首歌曲名的专辑信息
PREFIX music: <http://kg.course/music/>
SELECT ?trackID ?albumID ?name
WHERE {
?trackID music:track_name "track_name_00001" .
?trackID music:track_album ?albumID .
?ablumID music:album_name ?name
}
- 查询某一首歌曲名的专辑信息,使用中文来当变量名
PREFIX music: <http://kg.course/music/>
SELECT ?歌曲id ?专辑id ?专辑名
WHERE {
?歌曲id music:track_name "track_name_00001" .
?歌曲id music:track_album ?专辑id .
?专辑id music:album_name ?专辑名
}
5.查询某一首歌曲名的专辑信息,变量名添加描述
PREFIX music: <http://kg.course/music/>
SELECT ?歌曲id ?专辑id (CONCAT("专辑名",":",?专辑名) AS ?专辑信息)
WHERE {
?歌曲id music:track_name "track_name_00001" .
?歌曲id music:track_album ?专辑id .
?专辑id music:album_name ?专辑名
}
6.查询某个专辑里面的所有歌曲
PREFIX music: <http://kg.course/music/>
SELECT ?trackID
WHERE {
?albumID music:album_name "album_name_0002" .
?trackID music:track_album ?albumID
}
7.查询某个专辑里面的所有歌曲,限制前2
PREFIX music: <http://kg.course/music/>
SELECT ?trackID
WHERE {
?albumID music:album_name "album_name_0002" .
?trackID music:track_album ?albumID
}
limit 2
8.对某个专辑里面的所有歌曲计数
PREFIX music: <http://kg.course/music/>
SELECT (COUNT(?trackID) as ?num)
WHERE {
?albumID music:album_name "album_name_0002" .
?trackID music:track_album ?albumID
}
注意这个地方返回数据后面会有“^^xsd:integer”,这是jena数据库自己定义的数据结构, 如果做其他操作,也有可能是“xsd:string”或者“xsd:float”等
9.查询某一首歌是哪一个艺术家的作品
PREFIX music: <http://kg.course/music/>
SELECT ?trackID ?artistID
WHERE {
?trackID music:track_name "track_name_00001" .
?trackID music:track_artist ?artistID
}
10.查询某一首歌属于什么歌曲类型
PREFIX music: <http://kg.course/music/>
SELECT ?trackID ?tag_name
WHERE {
?trackID music:track_name "track_name_00001" .
?trackID music:track_tag ?tag_name
}
11.查询某一艺术家唱过歌曲的所有标签
PREFIX music: <http://kg.course/music/>
SELECT DISTINCT ?tag_name
WHERE {
?trackID music:track_artist music:artist_001 .
?trackID music:track_tag ?tag_name
}
12.查询某一艺术家唱过歌曲的所有类型并排序
PREFIX music: <http://kg.course/music/>
SELECT DISTINCT ?tag_name
WHERE {
?trackID music:track_artist music:artist_001 .
?trackID music:track_tag ?tag_name
}
ORDER BY ?tag_name
13.查询某几类歌曲标签中的歌曲的数目
PREFIX music: <http://kg.course/music/>
SELECT (COUNT(?trackID ) AS ?num)
WHERE {
{
?trackID music:track_tag "tag_name_01" .
}
UNION
{
?trackID music:track_tag "tag_name_02" .
}
}
PREFIX music: <http://kg.course/music/>
SELECT (count(?trackID ) as ?num)
WHERE {
?trackID music:track_tag ?tag_name
FILTER (?tag_name = "tag_name_01"|| ?tag_name = "tag_name_02")
}
14.查询所有歌曲中带有’xx’字符的歌曲名
PREFIX music: <http://kg.course/music/>
SELECT ?trackID ?tag_name
WHERE {
?trackID music:track_name ?track_name .
?trackID music:track_tag ?tag_name .
FILTER regex(?track_name,"088")
}
15.询问是否存在带有’xx’字符的歌曲名
PREFIX music: <http://kg.course/music/>
ASK
{
?trackID music:track_name ?track_name .
FILTER regex(?track_name,"008")
}
16.给艺术家id新增属性艺术家名字 这里首先需要更改注意更改操作url,将
/query
改为
/update
PREFIX music: <http://kg.course/music/>
INSERT DATA
{
music:artist_01 music:artist_name "artist_name_01" .
music:artist_02 music:artist_name "artist_name_02" .
music:artist_03 music:artist_name "artist_name_03" .
}
PREFIX music: <http://kg.course/music/>
SELECT ?artistID ?artist_name
WHERE {
?artistID music:artist_name ?artist_name
}
17.删除增加的属性艺术家名字
PREFIX music: <http://kg.course/music/>
DELETE
{
music:artist_02 music:artist_name ?x .
}
WHERE
{
music:artist_02 music:artist_name ?x .
}
PREFIX music: <http://kg.course/music/>
SELECT ?artistID ?artist_name
WHERE {
?artistID music:artist_name ?artist_name
}
|