知识图谱入门——知识存储

文章首发于博客du_ok’s Notes,本文链接为知识图谱入门——知识存储

本文首对一些开源数据库(如RDF4J、gStore),商业数据库(如Virtuoso、AllegroGraph和Stardog),以及一些原生的图数据库(如Neo4j、OrientDB和Titan)进行了粗略的介绍;接着介绍了一个使用Apache Jena数据库的例子。

图数据库介绍

图数据库源起欧拉和图理论 (graph theory),也可称为面向/基于图的数据库,对应的英文是Graph Database。图数据库的基本含义是以“图”这种数据结构存储和查询数据。它的数据模型主要是以节点和关系 (边)来体现,也可处理键值对。它的优点是快速解决复杂的关系问题。
图具有如下特征:

  • 包含节点和边
  • 节点上有属性 (键值对)
  • 边有名字和方向,并总是有一个开始节点和一个结束节点
  • 边也可以有属性

图数据库的分类如下:
知识图谱入门——知识存储_第1张图片

  • 原生数据库:包括基于main memory和基于disk。
  • 非原生数据库
    • RDBMS:基于关系数据库
      • Schema-based:需要设计表结构
      • Schema-free:不需要设计表结构
    • 基于NoSQL
      • Key-value:如Redis
      • Column family
      • Document store:如MongoDB
      • Graph database:如Neo4j(广义上的原生数据库)

开源数据库

开源数据库——RDF4J

  • 处理RDF数据的Java框架
  • 使用简单可用的API来实现
    RDF存储
  • 支持SPARQL endpoints
  • 支持两种RDF存储机制
  • 支持所有主流的RDF文件格式

开源图数据库——gStore

  • gStore从图数据库角度存储和检索RDF知识图谱数据;
  • gStore支持W3C定义的SPARQL 1.1标准,包括含有Union,OPTIONAL,FILTER和聚集函数的查询;gStore支持有效的增删改操作
  • gStore单机可以支持1Billion(十亿)三元组规模的RDF知识图谱的数据管理任务。

商业图数据库

Virtuoso

  • 智能数据,可视化与整合
  • 可扩展和高性能的数据管理
  • 支持Web 扩展和安全

Allgrograph

  • 一个现代的,高性能的,支持永久存储的图数据库
  • 基于Restful接入支持多语言编程

Stardog

知识图谱入门——知识存储_第2张图片

原生图数据库介绍

Neo4J

参见百度百科:Neo4j是一个高性能的,NOSQL图形数据库,它将结构化数据存储在网络上而不是表中。它是一个嵌入式的、基于磁盘的、具备完全的事务特性的Java持久化引擎,但是它将结构化数据存储在网络(从数学角度叫做图)上而不是表中。Neo4j也可以被看作是一个高性能的图引擎,该引擎具有成熟数据库的所有特性。

Neo4j的数据结构:
知识图谱入门——知识存储_第3张图片

  • 在一个图中包含两种基本的数据类型:Nodes (节点) 和Relationships (关系)。
  • Nodes 和 Relationships 包含key/value形式的属性。Nodes通过Relationships所定义的关系相连起来,形成关系型网络结构。

Neo4j数据导入:

  1. Cypher CREATE语句,为每一条数据写一个CREATE
  2. Cypher LOAD CSV 语句,将数据转成CSV格式,通过LOAD CSV读取数据
  3. 官方提供的Java API — Batch Inserter
  4. 官方提供的 neo4j-import 工具
  5. 第三方开发者编写的 Batch Import 工具

Neo4j数据存储:
知识图谱入门——知识存储_第4张图片

**Neo4j查询数据:**使用Cypher查询语言(基于遍历)
知识图谱入门——知识存储_第5张图片

OrientDB

OrientDB是一个用Java实现的开源NoSQL数据库管理系统。它是一个多模式的数据库,支持图形、文档、键值对、对象模型和关系,也可以为图数据库的管理与记录之间的提供连接。

Titan(小规模不推荐使用)

  • 弹性和线性增长的数据和用户的可扩展性
  • 数据分布和复制性能和容错性
  • 支持增删改查,支持一致性
  • 支持各种后端存储
  • 支持全局图数据分析,报告,并通过ETL连接大数据平台
  • 支持全文检索

Benchmark

常用的Benchmark

知识图谱入门——知识存储_第6张图片

常用衡量指标

  • Load Time
  • Repository Size
    当知识图谱越大时,希望读写性能呈线性增长时的斜率低
  • Query Response Time
    • 单Query:是否使用了Cache
    • 多Query:mix query使得cache失效,大多存在与冷启动,即cache无预先保存与Query相关的结果情况
  • Throughputs
    • 单Query
    • 多Query
  • Inference Support

一个知识存储的例子

Jena是一个免费开源的支持构建语义网络和数据链接应用的Java框架。
知识图谱入门——知识存储_第7张图片

  • 底层存储支持基于内存、基于SDB(导入关系数据库)、基于TDB(导入原生的三元组数据)和基于custom的存储;
  • 同时Jena还支持一些推理的API;
  • RDF API,支持基于SPARQL语言的查询;
  • 可使用Fuseki进行增删查改。

前期工作

定义一个音乐知识图谱的Schema如下:
知识图谱入门——知识存储_第8张图片

Schema中的蓝线指向属性,绿线指向实体,虚线指向图谱生成之后添加的属性,后面通过
SPARQL Update语句添加。

我们使用python脚本生成了1000个音乐知识图谱的三元组:
知识图谱入门——知识存储_第9张图片

数据导入:

  • 使用TDB导入
    使用tdbloader工具的命令为:
    /jena-fuseki/tdbloader --loc=/jena-fuseki/data filename
    

    '/jena-fuseki/data’是存储的位置。

  • 使用Fuseki导入

启动Fuseki服务:
在导入数据之后我们可以使用接口对我们的数据进行查询,于是我们使用Fuseki Server进行查询,启动命令如下,注意此处需要指定TDB生成的文件路径和数据库名:

/jena-fuseki/fuseki-server --loc=/jena-fuseki/data --update /music

其中/music是刚刚导入的数据

数据库查询方法:

  1. Fuseki界面查询
  2. 使用endpoint接口查询,endpoint地址为:
    SPARQL Query: http://localhost:3030/music/query
    SPARQL Update: http://localhost:3030/music/update
  3. 使用SPARQLWrapper包查询和更新(详见https://rdflib.github.io/sparqlwrapper/)
    知识图谱入门——知识存储_第10张图片

后两种方法都是可以基于Python语言。

查询示例

  1. 查询某一艺术家的所有歌曲
PREFIX music: 

SELECT  DISTINCT   ?trackID
WHERE { 
  ?trackID  music:track_artist  music:artist_01
}
  1. 查询某一艺术家的所有歌曲的歌曲名
PREFIX music: 

SELECT ?name
WHERE {
  ?trackID  music:track_artist music:artist_01  .
  ?trackID  music:track_name  ?name
 }
  1. 查询某一首歌曲名的专辑信息
PREFIX music: <http://kg.course/music/>

SELECT ?trackID ?ablumID ?name
WHERE { 
 ?trackID    music:track_name     "track_name_00001"  .  
 ?trackID    music:track_album    ?ablumID .
 ?ablumID    music:ablum_name     ?name 
}
  1. 查询某一首歌曲名的专辑信息,使用中文来当变量名
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   ?专辑名
}
  1. 查询某一首歌曲名的专辑信息,变量名添加描述
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   ?专辑名
}
  1. 查询某个专辑里面的所有歌曲
PREFIX music: <http://kg.course/music/>

SELECT  ?trackID
WHERE {
  ?albumID    music:album_name   "album_name_0002"  .  
  ?trackID    music:track_album   ?albumID 
}
  1. 查询某个专辑里面的所有歌曲,限制前2
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>

SELECT ?S  ?P
WHERE {
  ?subject  ?predicate  "ablum_name_0002" .
  ?S        ?P           ?subject
}
limit 2
  1. 对某个专辑里面的所有歌曲计数
PREFIX music: <http://kg.course/music/>

SELECT  (COUNT(?trackID) as ?num)
WHERE {
  ?albumID    music:album_name   "album_name_0002"  .  
  ?trackID    music:track_album   ?albumID 
}
  1. 查询某一首歌是哪一个艺术家的作品
PREFIX music: <http://kg.course/music/>

SELECT ?trackID  ?artistID 
WHERE {  
  ?trackID  music:track_name   "track_name_00001"  .  
  ?trackID music:track_artist ?artistID 
}
  1. s查询某一首歌属于什么歌曲类型
PREFIX music: <http://kg.course/music/>

SELECT  ?trackID ?tag_name 
WHERE {  
    ?trackID  music:track_name   "track_name_00001" .  
    ?trackID  music:track_tag    ?tag_name  
}
  1. 查询某一艺术家唱过歌曲的所有标签
PREFIX music: <http://kg.course/music/>

SELECT  DISTINCT ?tag_name
WHERE { 
    ?trackID    music:track_artist  music:artist_001  .  
    ?trackID    music:track_tag    ?tag_name
}
  1. 查询某一艺术家唱过歌曲的所有类型并排序
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
  1. 查询某几类歌曲标签中的歌曲的数目
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")
}
  1. 查询所有歌曲中带有’xx’字符的歌曲名
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
SELECT ?subject  ?object
WHERE {
  ?subject <http://kg.course/music/track_name>  ?object .
  FILTER  regex(?object,"088")
}
  1. 询问是否存在带有’xx’字符的歌曲名
PREFIX music: <http://kg.course/music/>
ASK  
{ 
  ?trackID  music:track_name  ?track_name . 
  FILTER    regex(?track_name,"008")
}

增加示例

给艺术家id新增属性艺术家名字

PREFIX music: <http://kg.course/music/>

INSERT DATA
{
  music:arttist_01  music:artist_name  "artist_name_01" . 
  music:arttist_02  music:artist_name  "artist_name_02" .
  music:arttist_03  music:artist_name  "artist_name_03" .
}
PREFIX music: <http://kg.course/music/>

SELECT  ?artistID  ?artist_name
WHERE {
  ?artistID  music:artist_name ?artist_name 
}

删除示例

删除增加的属性艺术家名字

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 
}

你可能感兴趣的:(Knowledge,Graph)