如何生成 RDF 数据?

本贴最后更新于 2627 天前,其中的信息可能已经时异事殊

版权声明:可以任意转载,转载时请标明文章原始出处和作者信息:石磊

背景

知识图谱越来越火,技术人员开始习惯使用 Sparql 查询 RDF 数据。但是,我们如何构建一个 RDF 数据呢?

因为之前互联网上没有相关工具介绍的文章,所以,这里,我对常见的两种 RDF 构造工具做一个介绍。

相关知识

RDF

“资源描述框架(Resource Description Framework,RDF)”成为 W3C 推荐标准,与 XML 和 SOAP 等 Web 标准并排。RDF 可以应用于处理特殊输入数据(如 CRM)的领域,已经广泛用于社会网络和自助出版软件(如 LiveJournal 和 TypePad)。

关于 RDF 推荐去阮一峰的资源描述框架 RDF 进行了解,因为其介绍的浅显易懂。

Sparql

比如说我们查询 mysql, 使用的是 sql 语言,那么我们查询 RDf 数据,使用的就是 SPARQL。

学习这个语言的话,推荐直接去官方学习:https://www.w3.org/TR/rdf-sparql-query/

介绍列表

  • Jena

    Java 语言编写的,具有推理功能,适合开发和技术研究使用。

  • rdflib

    Python 语言编写的,但是功能简单,有基本的查询和构建功能。

Jena

Java 程序员将越来越多地得益于具有使用 RDF 模型的技能。在本文中,我将带您体验惠普实验室的开放源代码 Jena Semantic Web Framework(请参阅 官网)的一些功能。您将了解如何创建和填充 RDF 模型,如何将它们持久存储到数据库中,以及如何使用 RDQL 查询语言以程序方式查询这些模型。最后,我将说明如何使用 Jena 的推理能力从本体推断模型知识。

对于专业人员来说,大家直接阅读官网就行,但是新手对官网很迷茫,不知道怎么看,所以将推荐看的东西说一下。

  1. 简单的 RDF 介绍和 Sparql 查询相结合:http://jena.apache.org/tutorials/rdf_api.html
  2. https://github.com/apache/jena/tree/master/jena-core/src-examples 这里有十个例子,结合博客把它看懂,基本操作就基本没问题了。

写 triple

下面的函数分为 SPO 中 O 是否是 Node 节点来区分。在注释中举了两个例子。并且在主函数中给出了一个测试方式。

import org.apache.jena.rdf.model.Model;
import org.apache.jena.rdf.model.ModelFactory;
import org.apache.jena.rdf.model.Property;
import org.apache.jena.rdf.model.RDFNode;
import org.apache.jena.rdf.model.Resource;

import config.Config;

public class WriteRdf {

	public static void main(String[] args) {
		// 函数示例
		Model model = ModelFactory.createDefaultModel();
		writeAnTripleWhenObjectIsNode(model, "数组", "分面", "二维数组");
		model.write(System.out, "N3");
	}

	/**
	 * 例子: <周杰伦> <年龄> '35'
	 */
	public static void writeAnTripleWhenObjectIsNotNode(Model model, String s, String p, String o) {

		Property property = model.createProperty(p);
		model.createResource(s).addProperty(property, o);
	}

	/**
	 * 例子: <周杰伦> <妻子> <昆凌>
	 */
	public static void writeAnTripleWhenObjectIsNode(Model model, String s, String p, String o) {
		Resource resource = model.createResource(s);
		Property property = model.createProperty(p);
		RDFNode object = model.createResource(o);
		model.add(resource, property, object);
	}

}

导入 RDF 数据到 Jena 中

RDF 数据格式有很多,但是 jena 内部的数据是以 TDB 形式存在的,需要把 RDf 这些文本文件转化为 jena 自己的模型。这里给出三种方法:


    public static void save1() {
    	String directory = "C:\\RDFdata\\Database1\\";
        Dataset ds = TDBFactory.createDataset(directory);
        Model model = ds.getDefaultModel();//这里使用TDB的默认Model
        String source = "C:\\RDFdata\\source\\drugs.nq";
        TDBLoader.loadModel(model, source); 
        ds.end();
        System.out.println("done");
	}

    public static void save2() {
    	String directory = "C:\\RDFdata\\Database2\\";
        Dataset ds = TDBFactory.createDataset(directory);
        Model model = ds.getDefaultModel();//这里使用TDB的默认Model
        FileManager.get().readModel(model, "C:\\RDFdata\\source\\drugs.nq");
        ds.end();
        System.out.println("done");
	}

    public static void save3()  {
		Dataset ds = TDBFactory.createDataset("D:\\RDFdata\\1\\");
		String filename = "D://rdf.nt2";
		RDFDataMgr.read(ds, filename,Lang.N3);
		ds.close();
		System.out.println(" done"); 
	}

### 查询

首先获取到 model

		Dataset ds = TDBFactory.createDataset("D:\\pdd\\");
		Model model = ds.getDefaultModel();

然后编写 sparql 语句,再进行查询

                String query111=
				"select (count(*) as ?num)" +
		        		" Where"+
						"{"+	
							"?s <http://kmap.xjtudlc.com/pdd_data/property/diagnoses_icd9>  ?o. "+
						"}";
		QueryExecution qexec = QueryExecutionFactory.create(query111, model);
		System.out.println(qexec.getQuery().toString());
		ResultSet resultSet = qexec.execSelect();

		String rerult = ResultSetFormatter.asText(resultSet);
		System.out.println(rerult);

输出形式有很多,也可以遍历进行输出,并输出自己想要的结果。

比如,我们想获取某一个属性 o,

	        ResultSet resultSet = qexec.execSelect();
		String o="";
		List<QuerySolution> rerult2 = ResultSetFormatter.toList(resultSet);
		System.out.println(rerult2.size());
		for (QuerySolution querySolution : rerult2) {
			o=querySolution.get("o").toString();
			System.out.println(o);
		}

其他

除了这些,jena 的特斯就是进行推理,可以将查询图进行分析。这里我用的不多,就不进行展示了。

rdflib

RDFLib 工作处理 RDF 是一个纯 Python 包。

RDFLib 包含大多数处理 RDF 的东西,包括:

  1. 解析和序列化 RDF/XML, N3, NTriples, N-Quads, Turtle, TriX, RDFa and Microdata.
  2. 一个图模型
  3. 存储模型.
  4. SPARQL 1.1 实现 - 支持 SPARQL 1.1 查询和更新数据.

官方网站: https://rdflib.readthedocs.io

### 导入文件

# 导入nt文件
from rdflib import Graph

g = Graph()

'''
format: 'rdf/xml' 'xml', 'n3', 'nt', 'trix', 'rdfa'
'''
g.parse("icd10.nt", format="n3")

# 打印图的大小
print(len(g))  # prints 2

# 遍历所有三元组
import pprint

for stmt in g:
    pprint.pprint(stmt)

支持的文件格式有:’rdf/xml’ ‘xml’, ‘n3’, ‘nt’, ‘trix’, ‘rdfa’

创建 RDF 文件

增加一个节点,并以 turtle 形式序列化输出

from rdflib import Graph
g = Graph()

g.add( (bob, RDF.type, FOAF.Person) )
g.add( (bob, FOAF.name, name) )
g.add( (bob, FOAF.knows, linda) )
g.add( (linda, RDF.type, FOAF.Person) )
g.add( (linda, FOAF.name, Literal('Linda') ) )

print g.serialize(format='turtle')

Sparql 查询

# 利用SPARQL进行查询
qres = g.query("""
    SELECT *
    WHERE {
      ?subject ?predicate  ?object
    } 
    LImit 10

""")

for row in qres:
    print(row)

对比

  1. python 版本的 rdflib 包 更简洁,语法简单,更容易理解
  2. rdflib 的官方文档更加简洁,符合新手的认知能力,建议初学者使用 python 来进行最好!
  3. Jena 文档首先需要吐槽,很不友好。
  4. Jena 的持久化做的比较好,在查询方式,序列化方式等方面做的更加专业。
  5. Jena 提供了持久化的事务能力。
  6. Jena 提供了远程调用方案,可以解决数据共享问题。我们可以开放一个 a SPARQL end-point 让其他人通过 http 连连接,就像 DBpedia 提供的查询接口一样。
  7. 总体来说,jena 更专业一点,rdflib 对新用户更友好,功能也够用。

PDD 与 我

我作为核心成员,发布了一个医疗的数据集 PDD,在 http://kmap.xjtudlc.com/pdd/ 同时,我们最近在整理最新的 ICD10 的数据集,与湘雅医院、腾讯的移动互联事业群(微信)在合作,准备利用知识图谱进行疾病诊断与药物推荐等方面工作。

  • 知识图谱
    2 引用 • 3 回帖
  • rdf
    2 引用 • 6 回帖
  • jena
    1 引用 • 3 回帖
  • Python

    Python 是一种面向对象、直译式电脑编程语言,具有近二十年的发展历史,成熟且稳定。它包含了一组完善而且容易理解的标准库,能够轻松完成很多常见的任务。它的语法简捷和清晰,尽量使用无异义的英语单词,与其它大多数程序设计语言使用大括号不一样,它使用缩进来定义语句块。

    545 引用 • 672 回帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...
  • xiaozhuzhu

    你好博主,请问使用 Jena 查询 RDF 数据时,
    Dataset ds = TDBFactory.createDataset("D:\pdd\"); Model model = ds.getDefaultModel();

    createDataset()函数中参数所代表的路径应该如何指定呢?是一个空的文件夹吗?

    1 回复
  • xjtushilei

    是一个你放了 jena 版本数据集的地方。如果你之前没有数据,那就指定为一个空的地方,第一次运行会生成默认的文件系统。之后这个文件夹就有东西了。但是里面是空的,需要你自己写进去一些三元组

  • xiaozhuzhu

    嗯嗯,刚刚仔细读了下楼主的代码和自己的代码,跑通了,谢谢。