結構化數據到RDF由兩種主要方式,一個是通過direct mapping,另一個通過R2RML語言這種,基於R2RML語言的方式更為靈活,定製性強。對於R2RML有一些好用的工具,此處我們使用d2rq工具,它基於R2RML-KIT。這裡和前面電影的有些重複,但側重點不同。

簡介

Direct mapping 本質上是通過編寫啟發式規則將資料庫中的錶轉換為RDF三元組, 但該方式靈活性不強。這裡我們用 D2RQ 工具,它的主要功能是提供以虛擬的、只讀的RDF圖形式進入到關係型資料庫中。也就是說比如你通過SPARQL埠查詢,輸入是SPARQL查詢語言,D2RQ通過mapping文件將其轉換為SQL語句在關係資料庫上查詢,因此實際上訪問的是關係型資料庫。同時你也可以使用它從資料庫創建 RDF 格式的文件。

D2RQ 由自己的mapping語言,R2RML-kit。它和W3C推薦的R2RML類似。你可以通過D2RQ提供的工具來根據資料庫自動生成mapping文件。你可以根據自己的需求去修改定製自己的mapping文件。

D2RQ 的框架如下圖所示:

D2RQ 的安裝

依賴:

  • java1.5及以上的JDK
  • 可用的資料庫,Oracle, SQL Server, PostgreSQL, MySQL or HSQLDB,都可以。我們這裡用 MYSQL.
  • 可選)J2EE servlet容器,D2R即可以作為一個獨立的Web伺服器運行,也可以在其他現有的servlet容器內運行。

之後就是安裝 D2RQ,首先下載D2RQ 安裝包,放到合適的位置:

wget https://github.com/downloads/d2rq/d2rq/d2rq-0.8.1.tar.gz;
tar -xvzf d2rq-0.8.1.tar.gz;

接下來根據所使用的資料庫安裝相應的 JDBC 驅動。把JAR文件放在D2R Server的/lib目錄下。Sun公司提供了一系列JDBC的下載,注意驅動的名字(e.g. org.postgresql.Driver for PostgreSQL or oracle.jdbc.driver.OracleDriver for Oracle),以及JDBC的URL(e.g. jdbc:mysql://servername/database for MySQL),這些在驅動的文件中可以找到。D2R Server中已經包括了MySQL和PostgreSQL。

D2RQ 的使用

生成 mapping 文件

使用 D2RQ 自帶的 generate-mapping 工具, 根據資料庫自動生成mapping文件。

./generate-mapping -u root -p nlp -o kg_demo_mapping_baidu_baike.ttl jdbc:mysql:///hudong_fenlei

其中 -u root 是資料庫的用戶名,-p nlp 是資料庫的密碼。 -o 指定生成 mapping 文件的名字。jdbc:mysql: /// 後面跟著的資料庫的名字。

通過上述命令,我們將得到如下的 mapping 文件:

@prefix map: <#> .
@prefix db: <> .
@prefix vocab: <vocab/> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix d2rq: <http://www.wiwiss.fu-berlin.de/suhl/bizer/D2RQ/0.1#> .
@prefix jdbc: <http://d2rq.org/terms/jdbc/> .

map:database a d2rq:Database;
d2rq:jdbcDriver "com.mysql.jdbc.Driver";
d2rq:jdbcDSN "jdbc:mysql:///hudong_fenlei";
d2rq:username "root";
d2rq:password "nlp";
jdbc:autoReconnect "true";
jdbc:zeroDateTimeBehavior "convertToNull";
.

# Table lemmas
map:lemmas a d2rq:ClassMap;
d2rq:dataStorage map:database;
d2rq:uriPattern "lemmas/@@lemmas.title_id@@";
d2rq:class vocab:lemmas;
d2rq:classDefinitionLabel "lemmas";
.
map:lemmas__label a d2rq:PropertyBridge;
d2rq:belongsToClassMap map:lemmas;
d2rq:property rdfs:label;
d2rq:pattern "lemmas #@@lemmas.title_id@@";
.
map:lemmas_title a d2rq:PropertyBridge;
d2rq:belongsToClassMap map:lemmas;
d2rq:property vocab:lemmas_title;
d2rq:propertyDefinitionLabel "lemmas title";
d2rq:column "lemmas.title";
.
map:lemmas_title_id a d2rq:PropertyBridge;
d2rq:belongsToClassMap map:lemmas;
d2rq:property vocab:lemmas_title_id;
d2rq:propertyDefinitionLabel "lemmas title_id";
d2rq:column "lemmas.title_id";
d2rq:datatype xsd:integer;
.
map:lemmas_abstract a d2rq:PropertyBridge;
d2rq:belongsToClassMap map:lemmas;
d2rq:property vocab:lemmas_abstract;
d2rq:propertyDefinitionLabel "lemmas abstract";
d2rq:column "lemmas.abstract";
.
map:lemmas_infobox a d2rq:PropertyBridge;
d2rq:belongsToClassMap map:lemmas;
d2rq:property vocab:lemmas_infobox;
d2rq:propertyDefinitionLabel "lemmas infobox";
d2rq:column "lemmas.infobox";
.
map:lemmas_subject a d2rq:PropertyBridge;
d2rq:belongsToClassMap map:lemmas;
d2rq:property vocab:lemmas_subject;
d2rq:propertyDefinitionLabel "lemmas subject";
d2rq:column "lemmas.subject";
.
map:lemmas_disambi a d2rq:PropertyBridge;
d2rq:belongsToClassMap map:lemmas;
d2rq:property vocab:lemmas_disambi;
d2rq:propertyDefinitionLabel "lemmas disambi";
d2rq:column "lemmas.disambi";
.
map:lemmas_redirect a d2rq:PropertyBridge;
d2rq:belongsToClassMap map:lemmas;
d2rq:property vocab:lemmas_redirect;
d2rq:propertyDefinitionLabel "lemmas redirect";
d2rq:column "lemmas.redirect";
.
map:lemmas_curLink a d2rq:PropertyBridge;
d2rq:belongsToClassMap map:lemmas;
d2rq:property vocab:lemmas_curLink;
d2rq:propertyDefinitionLabel "lemmas curLink";
d2rq:column "lemmas.curLink";
.
map:lemmas_interPic a d2rq:PropertyBridge;
d2rq:belongsToClassMap map:lemmas;
d2rq:property vocab:lemmas_interPic;
d2rq:propertyDefinitionLabel "lemmas interPic";
d2rq:column "lemmas.interPic";
.
map:lemmas_interLink a d2rq:PropertyBridge;
d2rq:belongsToClassMap map:lemmas;
d2rq:property vocab:lemmas_interLink;
d2rq:propertyDefinitionLabel "lemmas interLink";
d2rq:column "lemmas.interLink";
.
map:lemmas_exterLink a d2rq:PropertyBridge;
d2rq:belongsToClassMap map:lemmas;
d2rq:property vocab:lemmas_exterLink;
d2rq:propertyDefinitionLabel "lemmas exterLink";
d2rq:column "lemmas.exterLink";
.
map:lemmas_relateLemma a d2rq:PropertyBridge;
d2rq:belongsToClassMap map:lemmas;
d2rq:property vocab:lemmas_relateLemma;
d2rq:propertyDefinitionLabel "lemmas relateLemma";
d2rq:column "lemmas.relateLemma";
.
map:lemmas_all_text a d2rq:PropertyBridge;
d2rq:belongsToClassMap map:lemmas;
d2rq:property vocab:lemmas_all_text;
d2rq:propertyDefinitionLabel "lemmas all_text";
d2rq:column "lemmas.all_text";
.

但是這個 mapping 文件我們還不能使用,需要做一些修改:

  • vocab 這個我們不用,因此刪除開頭和正文中帶有 vocab 的部分
    • sed -i /@prefix vocab.* ./d kg_demo_mapping_hudong_fenlei.ttl
    • sed -i s/vocab/ /g kg_demo_mapping_hudong_fenlei.ttl
  • 因為我們有互動和百度兩個圖譜,因此需要指定不同的前綴,對於互動百科
    • sed -i 8a @prefix : http://www.kghudong.com# . kg_demo_mapping_hudong_fenlei.ttl
  • 因為是中文圖譜,因此要指定文字編碼:
    • sed -i s/d2rq:jdbcDSN "jdbc:mysql.*;/d2rq:jdbcDSN "jdbc:mysql:///hudong_fenlei?useUnicode=true&characterEncoding=utf8";/g kg_demo_mapping_hudong_fenlei.ttl

修改後,得到如下 mapping 文件:

@prefix map: <#> .
@prefix db: <> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix d2rq: <http://www.wiwiss.fu-berlin.de/suhl/bizer/D2RQ/0.1#> .
@prefix jdbc: <http://d2rq.org/terms/jdbc/> .
@prefix : <http://www.kghudong.com#> .

map:database a d2rq:Database;
d2rq:jdbcDriver "com.mysql.jdbc.Driver";
d2rq:jdbcDSN "jdbc:mysql:///hudong_fenlei?useUnicode=true&characterEncoding=utf8";
d2rq:username "root";
d2rq:password "nlp";
jdbc:autoReconnect "true";
jdbc:zeroDateTimeBehavior "convertToNull";
.

# Table lemmas
map:lemmas a d2rq:ClassMap;
d2rq:dataStorage map:database;
d2rq:uriPattern "lemmas/@@lemmas.title_id@@";
d2rq:class :lemmas;
d2rq:classDefinitionLabel "lemmas";
.
map:lemmas__label a d2rq:PropertyBridge;
d2rq:belongsToClassMap map:lemmas;
d2rq:property rdfs:label;
d2rq:pattern "lemmas #@@lemmas.title_id@@";
.
map:lemmas_title a d2rq:PropertyBridge;
d2rq:belongsToClassMap map:lemmas;
d2rq:property :lemmas_title;
d2rq:propertyDefinitionLabel "lemmas title";
d2rq:column "lemmas.title";
.
map:lemmas_title_id a d2rq:PropertyBridge;
d2rq:belongsToClassMap map:lemmas;
d2rq:property :lemmas_title_id;
d2rq:propertyDefinitionLabel "lemmas title_id";
d2rq:column "lemmas.title_id";
d2rq:datatype xsd:integer;
.
map:lemmas_abstract a d2rq:PropertyBridge;
d2rq:belongsToClassMap map:lemmas;
d2rq:property :lemmas_abstract;
d2rq:propertyDefinitionLabel "lemmas abstract";
d2rq:column "lemmas.abstract";
.
map:lemmas_infobox a d2rq:PropertyBridge;
d2rq:belongsToClassMap map:lemmas;
d2rq:property :lemmas_infobox;
d2rq:propertyDefinitionLabel "lemmas infobox";
d2rq:column "lemmas.infobox";
.
map:lemmas_subject a d2rq:PropertyBridge;
d2rq:belongsToClassMap map:lemmas;
d2rq:property :lemmas_subject;
d2rq:propertyDefinitionLabel "lemmas subject";
d2rq:column "lemmas.subject";
.
map:lemmas_disambi a d2rq:PropertyBridge;
d2rq:belongsToClassMap map:lemmas;
d2rq:property :lemmas_disambi;
d2rq:propertyDefinitionLabel "lemmas disambi";
d2rq:column "lemmas.disambi";
.
map:lemmas_redirect a d2rq:PropertyBridge;
d2rq:belongsToClassMap map:lemmas;
d2rq:property :lemmas_redirect;
d2rq:propertyDefinitionLabel "lemmas redirect";
d2rq:column "lemmas.redirect";
.
map:lemmas_curLink a d2rq:PropertyBridge;
d2rq:belongsToClassMap map:lemmas;
d2rq:property :lemmas_curLink;
d2rq:propertyDefinitionLabel "lemmas curLink";
d2rq:column "lemmas.curLink";
.
map:lemmas_interPic a d2rq:PropertyBridge;
d2rq:belongsToClassMap map:lemmas;
d2rq:property :lemmas_interPic;
d2rq:propertyDefinitionLabel "lemmas interPic";
d2rq:column "lemmas.interPic";
.
map:lemmas_interLink a d2rq:PropertyBridge;
d2rq:belongsToClassMap map:lemmas;
d2rq:property :lemmas_interLink;
d2rq:propertyDefinitionLabel "lemmas interLink";
d2rq:column "lemmas.interLink";
.
map:lemmas_exterLink a d2rq:PropertyBridge;
d2rq:belongsToClassMap map:lemmas;
d2rq:property :lemmas_exterLink;
d2rq:propertyDefinitionLabel "lemmas exterLink";
d2rq:column "lemmas.exterLink";
.
map:lemmas_relateLemma a d2rq:PropertyBridge;
d2rq:belongsToClassMap map:lemmas;
d2rq:property :lemmas_relateLemma;
d2rq:propertyDefinitionLabel "lemmas relateLemma";
d2rq:column "lemmas.relateLemma";
.
map:lemmas_all_text a d2rq:PropertyBridge;
d2rq:belongsToClassMap map:lemmas;
d2rq:property :lemmas_all_text;
d2rq:propertyDefinitionLabel "lemmas all_text";
d2rq:column "lemmas.all_text";
.

網頁端訪問

前面我們說 D2RQ提供虛擬的RDF訪問麼,現在我們來使用它。

首先進入到 d2rq文件夾內,運行

./d2r-server kg_demo_mapping_hudong_fenlei.ttl

命令開啟伺服器,然後通過網頁端進行訪問 http://localhost:2020/,順利的話,你應該看到如下界面

點進 lemmas,隨意打開一個,就可以看到該詞條的信息:

三元組的生成

在生成 mapping 文件後,通過

./dump-rdf -o hudong_baike.nt kg_demo_mapping_hudong_fenlei.ttl

命令將數據轉換為Ntriples。這一步比較慢,生成的文件也比較大,像互動百科有 430W 詞條,得到的nt文件大概59個G,因此要做好預留空間。

推薦閱讀:

相關文章