2005 年 6 月 13 日 隨著越來越多的數(shù)據(jù)使用類似 RSS 的 RDF 格式保存,一種新的需求產(chǎn)生了,即要求用一種簡(jiǎn)單方法查找特定信息。SPARQL 這個(gè)功能強(qiáng)大的新查詢語(yǔ)言填補(bǔ)了這個(gè)空白,使用戶可以很容易地在 RDF 的雜草從中找到所需的數(shù)據(jù)。本文將和您一起查看 SPARQL 的特性,學(xué)習(xí)如何利用 Jena 語(yǔ)義 Web 工具包,在自己的 Java 應(yīng)用程序中使用 SPARQL 查詢。 資源描述框架(Resource Description Framework),或 RDF,能夠?qū)?shù)據(jù)打散并分布開來。RDF 模型可以容易地合并在一起,而且序列化的 RDF 也可以簡(jiǎn)單地通過 HTTP 交換。應(yīng)用程序可以通過 Web 松散地耦合到多個(gè) RDF 數(shù)據(jù)源上。例如,在 PlanetRDF.com 上,我們把多個(gè)作者的 weblog 集中起來,作者們?cè)?RSS 1.0 feed 中用 RDF 提供內(nèi)容。作者 feed 的 URL 本身就放在 RDF 圖中,叫作 bloggers.rdf。 但是怎樣才能在 RDF 圖中發(fā)現(xiàn)并操縱需要的數(shù)據(jù)呢?SPARQL 協(xié)議和 RDF 查詢語(yǔ)言(SPARQL)目前是 W3C 的工作草案,還在討論當(dāng)中。SPARQL 構(gòu)建在以前的 RDF 查詢語(yǔ)言(例如 rdfDB、RDQL 和 SeRQL)之上,擁有一些有價(jià)值的新特性。在本文中,我們將用三種驅(qū)動(dòng) PlanetRDF 的 RDF 圖 —— 描述作者的 FOAF 圖、他們的 RSS 1.0 feed 以及 bloggers 圖 —— 來演示 SPARQL 能對(duì)數(shù)據(jù)做的一些有意思的事情。SPARQL 擁有針對(duì)各種平臺(tái)和語(yǔ)言的實(shí)現(xiàn);本文將重點(diǎn)介紹面向 Java 平臺(tái)的 Jena 語(yǔ)義 Web 工具包。 本文假設(shè)您有 RDF 的工作知識(shí),熟悉 RDF 的詞匯(例如 Dublin Core、FOAF 和 RSS 1.0)。此外,本文還假設(shè)您有一些使用 Jena 語(yǔ)義 Web 工具包的經(jīng)驗(yàn)。要想跟上所有這些技術(shù)的發(fā)展速度,請(qǐng)參閱后面 參考資料 部分中的鏈接。 一個(gè)簡(jiǎn)單 SPARQL 查詢的剖析 我們首先從查看 PlanetRDF 的 bloggers.rdf 模型開始。該模型非常簡(jiǎn)單,通過 FOAF 和 Dublin Core 詞匯為每個(gè) blog 投稿者提供名稱、blog 標(biāo)題和 URL。圖 1 顯示了一個(gè)投稿者的基本圖結(jié)構(gòu)。完整的模型只是為我們匯集的每一篇 blog 日志重復(fù)這個(gè)結(jié)構(gòu)而已。 圖 1. bloggers.rdf 中的一個(gè)投稿者的基本圖結(jié)構(gòu) 現(xiàn)在,我們來看一個(gè)針對(duì)博客模型的非常簡(jiǎn)單的 SPARQL 查詢。比方說以下這個(gè)查詢“根據(jù)名為 Jon Foobar 的人查找 blog 的 URL”,如清單 1 所示: 清單 1. 查找某一投稿者的 blog 的 URL 的 SPARQL 查詢 PREFIX foaf: <http://xmlns.com/foaf/0.1/> SELECT ?url FROM <bloggers.rdf> WHERE { ?contributor foaf:name "Jon Foobar" . ?contributor foaf:weblog ?url . } | 查詢的第一行只是為 FOAF 定義 PREFIX ,這樣就不必每次都用完整名稱引用它。SELECT 子句指定查詢應(yīng)當(dāng)返回的內(nèi)容,在這個(gè)例子中,返回的是名為 url 的變量。SPARQL 變量用 ? 或 $ 作為前綴,這兩個(gè)前綴是可以互換的,但在本文中,我堅(jiān)持使用 ? 作為前綴。FROM 是一個(gè)可選的子句,它提供了將要使用的數(shù)據(jù)集的 URI。在這里,它只是指向一個(gè)本地文件,但是它也可以指向 Web 其他地方的某一個(gè)圖的 URL。最后,WHERE 子句由一組三元模式組成,用基于 Turtle 的語(yǔ)法表示。這些三元模式共同構(gòu)成了所謂的圖形模式。 這個(gè)查詢?cè)噲D把圖形模式的三元模式和模型進(jìn)行匹配。將每個(gè)圖形模式變量的綁定與模型節(jié)點(diǎn)進(jìn)行匹配就成為一種查詢解決方案,而 SELECT 子句中指定的變量值則成為查詢結(jié)果的一部分。 在這個(gè)示例中,WHERE 子句的圖形模式中的第一個(gè)三元組與 foaf:name 屬性為“Jon Foobar”的節(jié)點(diǎn)匹配,并把它綁定到名為 contributor 的變量。在 bloggers.rdf 模型中,contributor 會(huì)和 圖 1 頂部的空節(jié)點(diǎn) foaf:Agent 匹配。圖形模式的第二個(gè)三元組與 contributor 的 foaf:weblog 屬性對(duì)應(yīng)的對(duì)象匹配。這被綁定到 url 變量,形成查詢結(jié)果。
在 Jena 中使用 SPARQL 支持在 Jena 中使用 SPARQL 目前可以通過叫作 ARQ 的模塊得以實(shí)現(xiàn)。除了實(shí)現(xiàn) SPARQL 之外,ARQ 的查詢引擎還可以解析使用 RDQL 或者它自己內(nèi)部的查詢語(yǔ)言表示的查詢。ARQ 的開發(fā)很活躍,但它還不是標(biāo)準(zhǔn) Jena 發(fā)行版本中的一部分。但是,可以從 Jena 的 CVS 倉(cāng)庫(kù)或者自包含的下載文件中獲得它。 讓 ARQ 運(yùn)行起來很簡(jiǎn)單。只需要得到最新的 ARQ 發(fā)行包(要獲得有關(guān)鏈接,請(qǐng)參閱后面 參考資料 部分),然后對(duì)其進(jìn)行解壓,把環(huán)境變量 ARQROOT 設(shè)置成指向 ARQ 目錄即可??赡苓€需要恢復(fù) ARQ bin 目錄的讀取和執(zhí)行權(quán)限。如果把 bin 目錄添加到執(zhí)行路徑中非常方便,那是因?yàn)樗瑥拿钚姓{(diào)用 ARQ 的包裝器腳本。為了確定所有設(shè)置都已到位,請(qǐng)從命令行調(diào)用 sparql ,確定看到了它的用法信息。清單 2 演示了所有步驟,清單 2 假設(shè)正在 UNIX 類的平臺(tái)上工作,或者是在 Windows 下用 Cygwin 工作。(ARQ 還附帶了在 Windows 下使用的.bat 腳本,但是它們用法和下面示例中的用法稍有差別。) 清單 2. 設(shè)置使用 Jena ARQ 的環(huán)境 $ export ARQROOT=~/ARQ-0.9.5 $ chmod +rx $ARQROOT/bin/* $ export PATH=$PATH:$ARQROOT/bin $ sparql Usage: [--data URL] [exprString | --query file] | 從命令行執(zhí)行 SPARQL 查詢 現(xiàn)在就可以運(yùn)行 SPARQL 查詢了(參見清單 3)。我們將使用來自 清單 1的數(shù)據(jù)集和查詢。因?yàn)椴樵兪褂?FROM 關(guān)鍵字指定要使用的圖,所以只需把查詢文件的位置提供給 sparql 命令行即可。但是,查詢需要在包含圖的目錄中運(yùn)行,因?yàn)樵搱D是在查詢的 FROM 子句中用相對(duì) URL 指定的。 清單 3. 用 sparql 命令執(zhí)行簡(jiǎn)單查詢 $ sparql --query jon-url.rq ---------------------------- | url | ============================ | <http://foobar.xx/blog> | ---------------------------- | 有時(shí),從查詢中忽略 FROM 子句很有意義。這樣就可以允許在執(zhí)行查詢的時(shí)候才把圖傳遞給它。當(dāng)從應(yīng)用程序代碼中使用 SPARQL 時(shí),避免把數(shù)據(jù)集綁定到查詢是一個(gè)好習(xí)慣 —— 例如,它允許把同一查詢重用在不同的圖上??梢栽诿钚杏?sparql --data URL 選項(xiàng)在運(yùn)行時(shí)指定圖,其中 URL 是圖的位置。這個(gè) URL 既可以是本地文件的位置,也可以是遠(yuǎn)程圖的 Web 地址。 用 Jena API 執(zhí)行 SPARQL 查詢 命令行 sparql 工具對(duì)于運(yùn)行獨(dú)立查詢有用,同時(shí) Java 應(yīng)用程序也可以直接調(diào)用 Jena 的 SPARQL 功能。通過 com.hp.hpl.jena.query 包中的類,使用 Jena 來創(chuàng)建和執(zhí)行 SPARQL 查詢。使用 QueryFactory 是最簡(jiǎn)單的方法。QueryFactory 有各種 create() 方法,用來從文件或者 String 讀取文本查詢。這些 create() 方法返回 Query 對(duì)象,這個(gè)對(duì)象封裝了解析后的查詢。 下一步是創(chuàng)建 QueryExecution 的實(shí)例,這個(gè)類表示查詢的一個(gè)執(zhí)行。要獲得 QueryExecution ,請(qǐng)調(diào)用 QueryExecutionFactory.create(query, model) ,并傳入要執(zhí)行的 Query 以及查詢要處理的 Model 。因?yàn)椴樵兊臄?shù)據(jù)是編程方式提供的,所以查詢不需要 FROM 子句。 QueryExecution 上有幾種不同的執(zhí)行方法,每個(gè)方法執(zhí)行一種不同類型的查詢(請(qǐng)參閱標(biāo)題為“其他類型的 SPARQL 查詢”的側(cè)欄,以獲得更多信息)。對(duì)于簡(jiǎn)單的 SELECT 查詢,可以調(diào)用 execSelect() ,該方法將返回 ResultSet 。ResultSet 支持在查詢返回的每個(gè) QuerySolution 上進(jìn)行迭代,這提供了對(duì)每個(gè)綁定變量值的訪問。另外,還可以使用 ResultSetFormatter ,以不同的格式輸出查詢結(jié)果。 清單 4 顯示了一個(gè)把這些步驟放在一起的簡(jiǎn)單方法。它執(zhí)行一個(gè)針對(duì) bloggers.rdf 的查詢,并把結(jié)果輸出到控制臺(tái)。 清間 4.用 Jena API 執(zhí)行一個(gè)簡(jiǎn)單查詢 // Open the bloggers RDF graph from the filesystem InputStream in = new FileInputStream(new File("bloggers.rdf")); // Create an empty in-memory model and populate it from the graph Model model = ModelFactory.createMemModelMaker().createModel(); model.read(in,null); // null base URI, since model URIs are absolute in.close(); // Create a new query String queryString = "PREFIX foaf: <http://xmlns.com/foaf/0.1/> " + "SELECT ?url " + "WHERE {" + " ?contributor foaf:name \"Jon Foobar\" . " + " ?contributor foaf:weblog ?url . " + " }"; Query query = QueryFactory.create(queryString); // Execute the query and obtain results QueryExecution qe = QueryExecutionFactory.create(query, model); ResultSet results = qe.execSelect(); // Output query results ResultSetFormatter.out(System.out, results, query); // Important - free up resources used running the query qe.close(); |
編寫更復(fù)雜的查詢 迄今為止,您已經(jīng)看到了兩種運(yùn)行簡(jiǎn)單 SPARQL 查詢的方法:用命令行 sparql 工具,用 Java 代碼調(diào)用 Jena API。在這一節(jié)中,我將介紹更多 SPARQL 的特性,以及它們支持的更復(fù)雜的查詢。 RDF 經(jīng)常被用來表示半結(jié)構(gòu)化的 數(shù)據(jù)。這意味著在一個(gè)模型中,兩個(gè)相同類型的節(jié)點(diǎn)可能有兩個(gè)不同的屬性集。例如,在 FOAF 模型中,對(duì)人的描述可能只包含電子郵件地址;而作為另一個(gè)選擇,它也可以包含真實(shí)名稱、IRC 昵稱、描繪個(gè)人照片的 URL,等等。 | 提煉查詢結(jié)果 為了進(jìn)一步提煉查詢的結(jié)果,SPARQL 擁有 DISTINCT 、LIMIT 、OFFSET 和 ORDER BY 關(guān)鍵字,它們操作或多或少與它們?cè)?SQL 中的對(duì)應(yīng)物有些類似。DISTINCT 可能只用在 SELECT 查詢上,格式為 SELECT DISTINCT 。它會(huì)從結(jié)果集中清除重復(fù)的查詢結(jié)果,讓留下的每個(gè)結(jié)果都是惟一的。其他關(guān)鍵字都放在查詢的 WHERE 子句之后。LIMIT n 把查詢返回的結(jié)果數(shù)量限制在 n 個(gè), 而 OFFSET n 則忽略前面 n 個(gè)結(jié)果。ORDER BY ?var 會(huì)根據(jù) ?var 的自然順序?qū)Y(jié)果進(jìn)行排序,例如,如果 var 是字符串值,則按字母順序排序??梢杂?ASC[?var] 和 DESC[?var] 指定排序的方向。 當(dāng)然,可以把 DISTINCT 、LIMIT 、OFFSET 和 ORDER BY 組合在查詢中。例如,可以用 ORDER BY DESC[?date] LIMIT 10 找到 RSS feed 中最新的十個(gè)條目。 | | 清單 5 顯示了一個(gè)非常小的 FOAF 圖,用 Turtle 語(yǔ)法表示。它包含對(duì) 4 個(gè)虛構(gòu)人物的描述,但是每個(gè)描述都有不同的屬性集。 清單 5. 一個(gè)描述 4 個(gè)虛構(gòu)人物的小 FOAF 圖 @prefix foaf: <http://xmlns.com/foaf/0.1/> . _:a foaf:name "Jon Foobar" ; foaf:mbox <mailto:jon@foobar.xx> ; foaf:depiction <http://foobar.xx/2005/04/jon.jpg> . _:b foaf:name "A. N. O'Ther" ; foaf:mbox <mailto:a.n.other@example.net> ; foaf:depiction <http://example.net/photos/an-2005.jpg> . _:c foaf:name "Liz Somebody" ; foaf:mbox_sha1sum "3f01fa9929df769aff173f57dec2fe0c2290aeea" _:d foaf:name "M Benn" ; foaf:depiction <http://mbe.nn/pics/me.jpeg> . | 可選匹配 假設(shè)您想編寫一個(gè)查詢,返回清單 5 的圖中所描述的每個(gè)人的名字,以及每個(gè)人的照片的鏈接(如果有照片的話)。在 foaf:depiction 中包含的圖形模式的 SELECT 查詢可能只會(huì)發(fā)現(xiàn)三個(gè)結(jié)果。Liz Somebody 不會(huì)形成結(jié)果,因?yàn)殡m然它有 foaf:name 屬性,但它沒有 foaf:depiction 屬性,而如果要與查詢匹配的話,那么這兩個(gè)屬性都需要。 幫助就在眼前,就是 SPARQL 的 OPTIONAL 關(guān)鍵字。可選塊 定義了附加圖形模式,即使模式不匹配,不會(huì)造成結(jié)果被拒絕,但在匹配的時(shí)候,圖形模式會(huì)被綁定到圖形上。清單 6 演示了一個(gè)查詢,在清單 5 的 FOAF 數(shù)據(jù)中查找每個(gè)人的 foaf:name ,而且可以選擇性地查找伴隨的 foaf:depiction 。 清單 6. 用可選塊查詢 FOAF 數(shù)據(jù) PREFIX foaf: <http://xmlns.com/foaf/0.1/> SELECT ?name ?depiction WHERE { ?person foaf:name ?name . OPTIONAL { ?person foaf:depiction ?depiction . } . } | 清單 7 顯示了運(yùn)行清單 6 的查詢的結(jié)果。所有查詢結(jié)果都包含人名,可選的圖形模式則只在 foaf:depiction 屬性存在的時(shí)候才綁定;如果沒有,就從結(jié)果中忽略。從這種意義上說,查詢與 SQL 中的左外連接相似。 清單 7. 清單 6 的查詢結(jié)果 ------------------------------------------------------------ | name | depiction | ============================================================ | "A. N. O'Ther" | <http://example.net/photos/an-2005.jpg> | | "Jon Foobar" | <http://foobar.xx/2005/04/jon.jpg> | | "Liz Somebody" | | | "M Benn" | <http://mbe.nn/pics/me.jpeg> | ------------------------------------------------------------ | 可選塊可以包含任何圖形模式,不僅僅是像清單 6 所示的那種單一的三元模式??蛇x塊中的所有查詢模式都匹配,才能讓可選模式成為查詢結(jié)果的一部分。如果查詢有多個(gè)可選塊,那么它們會(huì)分別發(fā)揮作用 —— 可能在結(jié)果中被忽略,也可能存在于結(jié)果中。可選塊也可以嵌套,在這種情況下,只有外部可選塊的模式與圖形匹配時(shí),才考慮內(nèi)部可選塊。 替換匹配 FOAF 圖形用人們的電子郵件地址來惟一地標(biāo)識(shí)他們。出于隱私的考慮,有些人喜歡用電子郵件地址的哈希碼。純文本的電子郵件地址用 foaf:mbox 屬性表示,而電子郵件地址的哈希碼則用 foaf:mbox_sha1sum 屬性表示;這兩個(gè)屬性在人們的 FOAF 描述中通常是互斥的。在這種情況下,可以用 SPARQL 的 替代匹配 特性來編寫查詢,該查詢返回任何可用的屬性。 替換匹配的定義方式是寫出多個(gè)替換圖形模式,中間用 UNION 關(guān)鍵字連接。清單 8 顯示的查詢?cè)?清單 5 中的 FOAF 中查找每個(gè)人的名字,以及他們的 foaf:mbox 或 foaf:mbox_sha1sum 。M Benn 不是查詢結(jié)果,因?yàn)樗葲]有 foaf:mbox 屬性也沒有 foaf:mbox_sha1sum 屬性。與 OPTIONAL 圖形模式相比,至少 要有一個(gè)替換模式和某個(gè)查詢結(jié)果匹配;如果UNION 匹配中的分支都匹配,那么會(huì)生成兩個(gè)結(jié)果。 清單 8. 有替代匹配的查詢和查詢結(jié)果 PREFIX foaf: <http://xmlns.com/foaf/0.1/> PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> SELECT ?name ?mbox WHERE { ?person foaf:name ?name . { { ?person foaf:mbox ?mbox } UNION { ?person foaf:mbox_sha1sum ?mbox } } } --------------------------------------------------------------------- | name | mbox | ===================================================================== | "Jon Foobar" | <mailto:jon@foobar.xx> | | "A. N. O'Ther" | <mailto:a.n.other@example.net> | | "Liz Somebody" | "3f01fa9929df769aff173f57dec2fe0c2290aeea" | --------------------------------------------------------------------- | 值約束條件 SPARQL 中的 FILTER 關(guān)鍵字對(duì)綁定變量的值進(jìn)行約束,從而限制查詢的結(jié)果。這些值約束條件是對(duì)布爾值進(jìn)行計(jì)算的邏輯表達(dá)式,并且可以與邏輯操作符 && 和 || 組合使用。例如,可以用過濾器把返回名稱列表的查詢修改成只返回和指定正則表達(dá)式匹配的名稱。或者,如清單 9 所示,過濾器在項(xiàng)目的出版日期上設(shè)置限制,從而找到 RSS feed 中在兩個(gè)特定日期之間發(fā)布的項(xiàng)目。清單 9 還顯示了如何使用 SPARQL 的 XPath 樣式的類型轉(zhuǎn)換特性(在這里,是將 date 變量轉(zhuǎn)換成 XML Schema 的 dateTime 值),以及如何用 ^^xsd:dateTime 在文字日期字符串上指定相同的數(shù)據(jù)類型。這可以確保在查詢中使用日期比較,而不是標(biāo)準(zhǔn)的字符串比較。 清單 9. 用過濾器檢索在 2005 年 4 月發(fā)布的 RSS feed 項(xiàng)目 PREFIX rss: <http://purl.org/rss/1.0/> PREFIX xsd: <http://www.w3.org/2001/XMLSchema#> PREFIX dc: <http://purl.org/dc/elements/1.1/> SELECT ?item_title ?pub_date WHERE { ?item rss:title ?item_title . ?item dc:date ?pub_date . FILTER xsd:dateTime(?pub_date) >= "2005-04-01T00:00:00Z"^^xsd:dateTime && xsd:dateTime(?pub_date) < "2005-05-01T00:00:00Z"^^xsd:dateTime } |
處理多個(gè)圖形 迄今為止,我所演示的所有查詢只包含一個(gè) RDF 圖的數(shù)據(jù)集。在 SPARQL 的術(shù)語(yǔ)中,這些查詢針對(duì)的是 后臺(tái)圖(background graph)。后臺(tái)圖是指:在使用 Jena 的 API 時(shí),通過某個(gè)查詢的 FROM 子句、sparql 命令的 --data 開關(guān)或者通過向 QueryExecutionFactory.create() 傳遞一個(gè)模型來指定的圖。 | 其他類型的 SPARQL 查詢 除了本文使用的 SELECT 查詢之外,SPARQL 還支持另外三種查詢。如果查詢的圖形模式在數(shù)據(jù)集中有匹配物,那么 ASK 將返回 “yes”,如果沒有匹配物,則返回 “no”。DESCRIBE 返回一個(gè)圖形,其中包含和圖形模式匹配的節(jié)點(diǎn)的相關(guān)信息。例如,DESCRIBE ?person WHERE { ?person foaf:name "Jon Foobar" } 會(huì)返回一個(gè)圖,其中包括來自 Jon Foobar 的模型的三元模式。最后,CONSTRUCT 用來為每個(gè)查詢結(jié)果輸出一個(gè)圖形模式。這樣就可以直接從查詢結(jié)果創(chuàng)建新的 RDF 圖。可以把 RDF 圖上的 CONSTRUCT 查詢想像成與 XML 數(shù)據(jù)的 XSL 轉(zhuǎn)換類似的東西。 | | 除了后臺(tái)圖,SPARQL 還能查詢?nèi)我鈹?shù)量的 命名圖。這些附加的圖是根據(jù)它們的 URI 來識(shí)別的,而這些 URI 在一個(gè)查詢內(nèi)是互不相同的。在研究使用命名圖的方法之前,我要解釋一下如何向查詢提供這些 URI。與后臺(tái)圖一樣,命名圖可以在查詢內(nèi)部用 FROM NAMED <URI> 指定,在這里,是通過 URI 來指定圖。另外,也可以用 --named URL 把命名圖提供給 sparql 命令,URL 用于指定圖的位置。最后,可以用 Jena 的 DataSetFactory 類指定要用編程方式查詢的命名圖。 在 SPARQL 查詢內(nèi)部用 GRAPH 關(guān)鍵字調(diào)用命名圖,后面是圖的 URI 或變量名。這個(gè)關(guān)鍵字后面是要與圖匹配的圖形模式。 在特定圖中查找匹配 當(dāng) GRAPH 關(guān)鍵字和圖的 URI(或者已經(jīng)綁定到圖的 URI 的變量)一起使用時(shí),圖形模式就被應(yīng)用到這個(gè) URI 標(biāo)識(shí)的任何圖。如果在指定的圖中發(fā)現(xiàn)匹配物,那么該匹配物就成為查詢結(jié)果的一部分。在清單 10 中,有兩個(gè) FOAF 圖被傳遞給查詢。查詢結(jié)果是在兩個(gè)圖中都可以發(fā)現(xiàn)的那些人的名字。注意,表示每個(gè) FOAF 圖的那些人的節(jié)點(diǎn)是空節(jié)點(diǎn),它們的作用范圍有限,只在包含它們的圖中有效。這意味著表示同一個(gè)人的節(jié)點(diǎn)不能在查詢的兩個(gè)命名圖中同時(shí)存在,所以必須用不同的變量 (x 和 y )來表示它們。 清單 10. 查找在兩個(gè)命名 FOAF 圖中都描述的那些人的查詢 PREFIX foaf: <http://xmlns.com/foaf/0.1/> PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> SELECT ?name FROM NAMED <jon-foaf.rdf> FROM NAMED <liz-foaf.rdf> WHERE { GRAPH <jon-foaf.rdf> { ?x rdf:type foaf:Person . ?x foaf:name ?name . } . GRAPH <liz-foaf.rdf> { ?y rdf:type foaf:Person . ?y foaf:name ?name . } . } | 查找包含某個(gè)模式的圖 使用 GRAPH 的另一種方法是在它后面跟一個(gè)未綁定變量。在這種情況下,圖形模式被應(yīng)用到查詢可以使用的每個(gè)命名圖中。如果模式和其中一個(gè)命名圖匹配,那么這個(gè)圖的 URI 就被綁定到 GRAPH 的變量上。清單 11 的 GRAPH 子句和提供給查詢的命名圖中的每個(gè)人員節(jié)點(diǎn)匹配。匹配的人名被綁定到 name 變量,而 graph_uri 變量綁定到與模式匹配的圖的 URI 上。查詢的結(jié)果也顯示出來。有一個(gè)名稱 A. N. O'Ther 被匹配了兩次,因?yàn)樵?jon-foaf.rdf 和 liz-foaf.rdf 中都描述了這個(gè)人。 清單 11. 確定哪個(gè)圖描述了不同的人 PREFIX foaf: <http://xmlns.com/foaf/0.1/> PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> SELECT ?name ?graph_uri FROM NAMED <jon-foaf.rdf> FROM NAMED <liz-foaf.rdf> WHERE { GRAPH ?graph_uri { ?x rdf:type foaf:Person . ?x foaf:name ?name . } } -------------------------------------------------------- | name | graph_uri | ======================================================== | "Liz Somebody" | <file://.../jon-foaf.rdf> | | "A. N. O'Ther" | <file://.../jon-foaf.rdf> | | "Jon Foobar" | <file://.../liz-foaf.rdf> | | "A. N. O'Ther" | <file://.../liz-foaf.rdf> | -------------------------------------------------------- | | XML 格式的查詢結(jié)果 SPARQL 允許以 XML 格式返回查詢結(jié)果,采用的格式叫作 SPARQL 變量綁定結(jié)果 XML 格式。這個(gè)用 schema 定義的格式是 RDF 查詢和 XML 工具及庫(kù)之間的橋梁。 這項(xiàng)功能還有許多潛在用途??梢园?SPARQL 查詢的結(jié)果通過 XSLT 轉(zhuǎn)換成 Web 面或 RSS feed,通過 XPath 訪問結(jié)果,或者把結(jié)果文件返回給 SOAP 或 AJAX 客戶。要以 XML 格式返回查詢結(jié)果,請(qǐng)使用 ResultSetFormatter.outputAsXML() 方法,或者在命令行指定 --results rs/xml 。 | | 組合后臺(tái)數(shù)據(jù)和命名圖 查詢也可以把后臺(tái)數(shù)據(jù)和命名圖結(jié)合在一起使用。清單 12 用來自 PlanetRDF.com 的活動(dòng)的聚合 RSS feed 作為后臺(tái)數(shù)據(jù),結(jié)合一個(gè)包含我自己的配置檔案的命名圖對(duì)它進(jìn)行查詢。我的想法是創(chuàng)建一個(gè)個(gè)性化的 feed,找到我認(rèn)識(shí)的一些博客最新發(fā)表的十個(gè)貼子。查詢的第一部分找到了 FOAF 文件中代表我的那些節(jié)點(diǎn),然后找到了圖中描述的、我認(rèn)識(shí)的那些人的名字。第二部分在這些人創(chuàng)建的 RSS feed 中查找項(xiàng)目。最后,按照項(xiàng)目的創(chuàng)建時(shí)間對(duì)結(jié)果集進(jìn)行排序,而且限制只返回十個(gè)結(jié)果。 清單 12. 得到一個(gè)個(gè)性化的活躍的 PlanetRDF feed PREFIX foaf: <http://xmlns.com/foaf/0.1/> PREFIX rss: <http://purl.org/rss/1.0/> PREFIX dc: <http://purl.org/dc/elements/1.1/> SELECT ?title ?known_name ?link FROM <http://planetrdf.com/index.rdf> FROM NAMED <phil-foaf.rdf> WHERE { GRAPH <phil-foaf.rdf> { ?me foaf:name "Phil McCarthy" . ?me foaf:knows ?known_person . ?known_person foaf:name ?known_name . } . ?item dc:creator ?known_name . ?item rss:title ?title . ?item rss:link ?link . ?item dc:date ?date. } ORDER BY DESC[?date] LIMIT 10 | 雖然這個(gè)查詢只是返回標(biāo)題、名稱和 URL 的列表,但是更復(fù)雜的查詢可以從匹配項(xiàng)目提取出所有數(shù)據(jù)。采用 SPARQL 的 XML 結(jié)果格式(請(qǐng)參閱標(biāo)題為“XML 格式的查詢結(jié)果”的側(cè)欄)與 XSL 樣式表結(jié)合,還可以創(chuàng)建博客日志的個(gè)性化的 HTML 視圖,甚至生成另一個(gè) RSS feed。
結(jié)束語(yǔ) 本文中的示例應(yīng)當(dāng)有助于您理解 SPARQL 的基本特性和語(yǔ)法,以及它帶給 RDF 應(yīng)用程序的好處。還了解了SPARQL 如何在可選和可替換匹配的幫助下,讓您了解真實(shí)的 RDF 圖的半結(jié)構(gòu)化特性。使用命名圖的示例還顯示了如何使用 SPARQL 組合多個(gè)圖來啟用查詢選項(xiàng)。您還看到在 Java 代碼中用 Jena API 運(yùn)行 SPARQL 是多么簡(jiǎn)單。 對(duì)于 SPARQL,還有更多這里可能沒有介紹的內(nèi)容,所以請(qǐng)利用下面的 參考資料 查找關(guān)于 SPARQL 特性的更多內(nèi)容。請(qǐng)參閱 SPARQL 的規(guī)范,詳細(xì)學(xué)習(xí) SPARQL 的內(nèi)置函數(shù)、操作符、查詢格式和語(yǔ)法,或者參閱更多 SPARQL 查詢示例。 當(dāng)然,學(xué)習(xí) SPARQL 的最好方法是編寫一些自己的查詢。從 Web 上得到一些 RDF 數(shù)據(jù),下載 Jena ARQ 模塊,開始體驗(yàn)吧!
參考資料
關(guān)于作者 | | | Philip McCarthy 是專門研究 Java 和 Web 技術(shù)的軟件開發(fā)顧問,目前正在位于 Bristol 的 HP 實(shí)驗(yàn)室為 HP 的數(shù)字媒體平臺(tái)計(jì)劃工作。他還是 PlanetRDF.com 幕后的團(tuán)隊(duì)成員之一,這是一個(gè)語(yǔ)義 Web 開發(fā)人員的社區(qū)站點(diǎn)。您可以通過 phil@planetrdf.com 與 Phil 聯(lián)系。 |
|