Jena对本体、RDF三元组的API操作记录
目錄
目標(biāo)
導(dǎo)入RDF
導(dǎo)入本體文件
新增三元組
(1)Statement方式
(2)Resource方式
問題記錄
參考文獻(xiàn)
目標(biāo)
? ? ? ? 通過這份源碼以及對(duì)應(yīng)配套的博客內(nèi)容的學(xué)習(xí),基本上是了解和掌握了知識(shí)圖譜的一些基本信息,如果你認(rèn)真看了作者寫的那幾篇文檔,應(yīng)該有了以下幾點(diǎn)的了解和認(rèn)識(shí):
(1)清楚的了解RDF/RDFS/OWL是什么,之間是什么關(guān)系,以及他們的簡(jiǎn)單用法
(2)搞清了本體、實(shí)體、三元組、TDB、Fuseki這些名詞的概念和作用
(3)知道本體文件應(yīng)該怎么編寫,知道怎么從關(guān)系mysql關(guān)系數(shù)據(jù)庫(kù)中將數(shù)據(jù)導(dǎo)出生成.nt三元組數(shù)據(jù)
(4)大致了解如何通過sparql通過Fuseki進(jìn)行三元組的查詢
(5)大致知道怎么通過知識(shí)庫(kù)圖譜進(jìn)行對(duì)話問答系統(tǒng)的建設(shè)
在此,在此感謝作者的總結(jié)和貢獻(xiàn)。
? ? ? ? 本篇主要記錄下,如何直接通過jena的API進(jìn)行本體導(dǎo)入、RDF三元組數(shù)據(jù)導(dǎo)入以及對(duì)三元組數(shù)據(jù)的增刪改查操作,實(shí)際上網(wǎng)上有很多優(yōu)秀的博文,我主要是記錄下我在學(xué)習(xí)的過程中遇到的問題。
(1)將ttl本體文件導(dǎo)入到TDB中
(2)將.nt數(shù)據(jù)直接導(dǎo)入到TDB中
(3)在TDB中創(chuàng)建指定model名稱的model,并且支持往model里新增、刪除三元組
(4)從TDB中查詢新增的三元組數(shù)據(jù)
? ? ? ? 注:jena版本3.6
導(dǎo)入RDF
? ? ? ? 在官網(wǎng)以及一些博客上可以很容易查到關(guān)于RDF導(dǎo)入的操作,主要包括兩種情況。 一種是直接從.nt文件中加載,加載到內(nèi)存中,然后進(jìn)行各種查詢。
? ? ? ? 一種是將.nt文件加載到TDB中,然后通過Dataset進(jìn)行查詢。
? ? ? ? 我主要考慮第二種,主要是為了持久化做準(zhǔn)備,可以新增三元組,而且TDB也可以暴露出去給Fuseki,供上層查詢使用。
String tdbPath = "/opt/tdb1"; String rdfFile = "/opt/rdf/kg_movie.nt"; String modelName = "KgMovie";Dataset ds = TDBFactory.createDataset(tdbPath);Model model = ds.getNamedModel(modelName); RDFDataMgr.read(model,rdfFilePath);ds.cose();? ? ? ? 這幾行代碼非常簡(jiǎn)單,網(wǎng)上還有很多其他方式的,比如通過FileManager.get()獲取文件流,然后再通過model.read去做的。都可以,不過有些方法可能逐步會(huì)被遺棄掉。使用的時(shí)候,查一下官方的API說明。
? ? ? ? 另外,有些博客提到事務(wù),比如ds.begin(ReadWrite.WRITE)、model.begin()、model.commit()等,也可以用,但是我沒發(fā)現(xiàn)有什么很特別的意義,不使用也是沒關(guān)系。?
導(dǎo)入本體文件
public boolean loadOntModel(String modelName, String ttlFilePath){if(!ds.isInTransaction())ds.begin(ReadWrite.WRITE);try{if(ds.containsNamedModel(modelName)){logger.warn("已經(jīng)存在對(duì)應(yīng)本體描述!");ds.commit();return false;}Model model = RDFDataMgr.loadModel(ttlFilePath);ds.addNamedModel(modelName,model);ds.commit();logger.info("{}本體描述已導(dǎo)入",modelName);}catch (Exception e){logger.error(CommTool.getStackTraceInfo(e));return false;}finally{if(ds.isInTransaction())ds.end();}return true;}? ? ? ? 這段代碼可以看到,先通過RDFDataMgr.loadModel直接記載ttl的本體文件到一個(gè)模型中,然后將模型放到Dataset中,ds是DataSet,通過TDBFactory.createDataset(tdbPath)創(chuàng)建的。 執(zhí)行完之后,會(huì)在對(duì)應(yīng)的TDB目錄下創(chuàng)建如下的文件:
? ? ? ? 同樣導(dǎo)入RDF的時(shí)候也會(huì)創(chuàng)建這些。?
?TDB存儲(chǔ)的本體數(shù)據(jù)集由node表、Triple和Quad索引、prefixes表組成,存放在指定的文件系統(tǒng)目錄下。TDB采用B+樹維護(hù)三種基本形式的Triple索引:SPO、POS和OSP(S、P、O分別代表Subject、Predicate和Object)。若存在命名圖(Named Graph),則同時(shí)維護(hù)相應(yīng)的Quad索引(G表示Graph):GOSP、SPOG、GSPO、OSPG、GPOS和POSG。
在實(shí)際操作中,以下幾點(diǎn)非常重要。
新增三元組
? ? ? ? 網(wǎng)上關(guān)于新增三元組的方式我查到的有三種,一種是通過Statement,mode.add的方式,一種是直接通過Resourece的方式,還有一種是直接通過Sparql的Insert語(yǔ)句。 前面兩種我都做了嘗試,都是沒有問題的。
(1)Statement方式
public static void test4(){String directory = "D:\\jena\\ctd" ;Dataset dataset = TDBFactory.createDataset(directory) ;String perx_s = "http://www.jingu.com#/movie/121";//電影String perx_p = "http://www.jingu.com#/movieTitle";String perx_o = "行尸走肉大暴亂";Model model = dataset.getNamedModel("kgMovie");Selector selector = new SimpleSelector(model.createResource(perx_s),model.createProperty(perx_p),model.createResource(perx_o));StmtIterator it = model.listStatements(selector);if(it.hasNext()){System.out.println("已存在");Statement stmt = model.createStatement(model.createResource(perx_s),model.createProperty(perx_p),model.createResource(perx_o));model.remove(stmt);System.out.println("已刪除");}else{Statement stmt = model.createStatement(model.createResource(perx_s),model.createProperty(perx_p),model.createResource(perx_o));model.add(stmt);System.out.println("已添加");}dataset.close();}? ? ? ? 代碼其實(shí)很簡(jiǎn)單,就是直接寫入一個(gè)三元組數(shù)據(jù),這種方式,從我目前理解來說,我覺得不如Resource方式直觀,Resource方式可以維護(hù)關(guān)系,維護(hù)屬性,維護(hù)類型等等。
? ? ? ? 這里可以看到有model.remove的方法,通過remove將三元組刪除掉。 這種刪除方式意味著需要先查詢,然后再remove掉。
(2)Resource方式
public static void addSPO(){String NS = "http://www.kgdemo.com#";String directory = "D:\\jena\\ctd" ;Dataset dataset = TDBFactory.createDataset(directory) ;Model model = dataset.getNamedModel("kgMovie");Resource movieClass = ResourceFactory.createResource(NS+"Movie");Property movieTitle = ResourceFactory.createProperty(NS,"movieTitle");Property movieReleaseDate = ResourceFactory.createProperty(NS,"movieReleaseDate");Resource m1 = model.createResource(NS+"movie/2");m1.addProperty(RDF.type,movieClass);m1.addProperty(movieTitle,"大戶西游2");m1.addProperty(movieReleaseDate,"2022-10-22");model.commit();dataset.close();}? ? ? ? 這種方式和ttl能夠?qū)Φ纳?#xff0c;正常情況下,我們肯定也是先設(shè)計(jì)ttl本體模式層,然后再進(jìn)行三元組數(shù)據(jù)生產(chǎn)。 可以通過mysql導(dǎo)入,也可以直接通過界面化的方式新增三元組。 通過界面方式新增三元的方式,就要求我們需要自己按照規(guī)范寫入三元組數(shù)據(jù)。?
? ? ? ? 通過Resource的方式,可以設(shè)置class,設(shè)置rdf:type,可以設(shè)置Property屬性等等。 代碼可以將整個(gè)本體描述的規(guī)范都體現(xiàn)出來。還是非常方便。
問題記錄
? ? ? ? 我實(shí)際預(yù)期想要實(shí)現(xiàn)的功能是通過Jena API將ttl本體描述文件或者.nt文件的數(shù)據(jù)導(dǎo)入到TDB中,往TDB中通過api新增三元組數(shù)據(jù),然后通過sparql將新增的三元組數(shù)據(jù)查詢出來。?
? ? ? ? 貼一段查詢的代碼,如下:
public static void test5(){String directory = "D:\\jena\\ctd" ;Dataset dataset = TDBFactory.createDataset(directory) ;// Potentially expensive query.String sparqlQueryString = "SELECT distinct ?s ?p ?o where { ?s ?p ?o}" ;// See http://incubator.apache.org/jena/documentation/query/app_api.htmlModel model = dataset.getNamedModel("kgMovie");Query query = QueryFactory.create(sparqlQueryString) ;QueryExecution qexec = QueryExecutionFactory.create(query, model) ;try {ResultSet results = qexec.execSelect() ;System.out.println(results.hasNext());for ( ; results.hasNext() ; ){QuerySolution soln = results.nextSolution() ;String count =soln.get("o").toString();logger.info("{}-->{}-->{}",soln.get("s"),soln.get("p"),soln.get("o"));}} finally { qexec.close() ; }// Close the dataset.dataset.close();}? ? ? ? 這段代碼中,QueryExecutionFactory.create的第二個(gè)入?yún)⒖梢允莇ataset,也可以是model,如果直接使用的dataset,會(huì)發(fā)現(xiàn)不管怎樣都查詢不到新增進(jìn)來的三元組,如果使用model就可以查詢到。?
? ? ? ? 也就是說,在新增三元組的時(shí)候,往那個(gè)model里新增了,查詢的時(shí)候就到那個(gè)model里查詢。 dataset默認(rèn)應(yīng)該是defaultModel,并不是全部。?
? ? ? ? 至此,除了查詢、推理這塊,整個(gè)界面化知識(shí)圖譜所需要的技術(shù)基本都調(diào)研完畢,后續(xù)我們可以進(jìn)行界面化的構(gòu)建本體、新增和維護(hù)三元組數(shù)據(jù)到指定modelName的模型中去,并提供查詢接口供上層KBQA使用。
參考文獻(xiàn)
【1】使用Jena-TDB存儲(chǔ)RDF本體、知識(shí)圖譜文件
【2】導(dǎo)入本體到Jena TDB數(shù)據(jù)庫(kù)
總結(jié)
以上是生活随笔為你收集整理的Jena对本体、RDF三元组的API操作记录的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 项目管理十大管理过程和知识领域思维导图(
- 下一篇: linux 修复ntfs磁盘,安装和使用