背景
知識圖譜越來越火,技術人員開始習慣使用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 的推理能力從本體推斷模型知識。
對於專業人員來說,大家直接閱讀官網就行,但是新手對官網很迷茫,不知道怎麼看,所以將推薦看的東西說一下。
- 簡單的RDF介紹和Sparql查詢相結合:http://jena.apache.org/tutorials/rdf_api.html
- 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的東西,包括:
- 解析和序列化 RDF/XML, N3, NTriples, N-Quads, Turtle, TriX, RDFa and Microdata.
- 一個圖模型
- 存儲模型.
- 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)
對比
- python版本的rdflib包 更簡潔,語法簡單,更容易理解
- rdflib 的官方文檔更加簡潔,符合新手的認知能力,建議初學者使用python來進行最好!
- Jena 文檔首先需要吐槽,很不友好。
- Jena的持久化做的比較好,在查詢方式,序列化方式等方面做的更加專業。
- Jena 提供了持久化的事務能力。
- Jena提供了遠程調用方案,可以解決數據共享問題。我們可以開放一個a SPARQL end-point 讓其他人通過http連連接,就像DBpedia提供的查詢接口一樣。
- 總體來說,jena更專業一點,rdflib對新用戶更友好,功能也夠用。
PDD 與 我
作爲核心成員,發佈了一個醫療的數據集PDD,在 http://kmap.xjtudlc.com/pdd/ 同時,我們最近在整理最新的ICD10的數據集,與湘雅醫院、騰訊的醫療大數據實驗室在合作,準備利用知識圖譜進行疾病輔助診斷與藥物推薦等方面工作。