2017-03-13 31 views
1

我是新來SPARQL,和圖形數據庫查詢作爲一個整體,所以請原諒任何無知,但我想寫使用存儲內Fueski一些數據的基本輸出和我在努力理解處理由於各種概念之間存在的基數而導致的行重複的最佳實踐。SPARQL多值屬性 - 描繪結果

我會用一個簡單的例子來希望證明我的觀點。

數據集

這是類型的數據和我目前的工作關係的代表性樣本;

Data Set

基於我已經產生了以下的三元組(N-三重格式)本結構;

<http://www.test.com/ontologies/Author/JohnGrisham> <http://www.test.com/ontologies/property#firstName> "John" . 
<http://www.test.com/ontologies/Author/JohnGrisham> <http://www.test.com/ontologies/property#lastName> "Grisham" . 
<http://www.test.com/ontologies/Author/JohnGrisham> <http://www.test.com/ontologies/property#hasWritten> <http://www.test.com/ontologies/Book/TheClient> . 
<http://www.test.com/ontologies/Author/JohnGrisham> <http://www.test.com/ontologies/property#hasWritten> <http://www.test.com/ontologies/Book/TheFirm> . 

<http://www.test.com/ontologies/Book/TheFirm> <http://www.test.com/ontologies/property#name> "The Firm" . 
<http://www.test.com/ontologies/Book/TheFirm> <http://www.test.com/ontologies/property#soldBy> <http://www.test.com/ontologies/Retailer/Foyles> . 
<http://www.test.com/ontologies/Book/TheFirm> <http://www.test.com/ontologies/property#soldBy> <http://www.test.com/ontologies/Retailer/Waterstones> . 

<http://www.test.com/ontologies/Book/TheClient> <http://www.test.com/ontologies/property#name> "The Client" . 
<http://www.test.com/ontologies/Book/TheClient> <http://www.test.com/ontologies/property#soldBy> <http://www.test.com/ontologies/Retailer/Amazon> . 
<http://www.test.com/ontologies/Book/TheClient> <http://www.test.com/ontologies/property#soldBy> <http://www.test.com/ontologies/Retailer/Waterstones> . 


<http://www.test.com/ontologies/Retailer/Amazon> <http://www.test.com/ontologies/property#name> "Amazon" . 
<http://www.test.com/ontologies/Retailer/Waterstones> <http://www.test.com/ontologies/property#name> "Waterstones" . 
<http://www.test.com/ontologies/Retailer/Foyles> <http://www.test.com/ontologies/property#name> "Foyles" . 

渲染輸出格式

現在我所要做的是使其中顯示的所有作者顯示的所有書籍的細節以及這些個人的書籍銷售的零售商的頁面。所以像這樣(suedo代碼);

for-each:Author 

    <h1>Author.firstName + Author.lastName</h1> 

    for-each:Author.Book 

    <h2>Book.Name</h2> 

    Sold By: 
    for-each:Book.Retailer 

     <h2>Retailer.name</h2> 

SPARQL

對於渲染工作,我的想法是,我需要作者的名字和姓氏,然後他們都本書的名字和各種零售商名稱那些書都是通過出售,因此我想出了以下SPARQL;

PREFIX p: <http://www.test.com/ontologies/property#> 

SELECT ?authorfirstname 
     ?authorlastname 
     ?bookname 
     ?retailername 
WHERE { 
    ?author p:firstName ?authorfirstname; 
      p:lastName ?authorlastname; 
      p:hasWritten ?book . 
    OPTIONAL { 
     ?book p:name ?bookname; 
       p:soldBy ?retailer . 
     ?retailer p:name ?retailername . 
    } 
} 

這提供了以下結果;

Results Triple Table

不幸的是,由於行的重複我的基本渲染的嘗試不能產生輸出不如預期,實際上它的渲染,每行一個新的「作者」部分從查詢返回。

我猜我想了解的是如何把這個類型的渲染應該做的。

  • 難道應該重新組合數據回曲線的形式就是了travese渲染器(老實說,我看不出這可能是這種情況)

  • 是SPARQL的無效 - 在那裏辦法做什麼,我想在SPARQL語言本身?

  • 我只是做一些完全錯誤的?

修訂 - 對GROUP_CONCAT更詳細的分析

在審查提供給我的選項我碰到GROUP_CONCAT但一點用它打出來後決定它可能不是說要去選擇給我想要的東西,可能不是最好的路線。原因是這樣的;

數據大小

雖然我在運行我的例子在這篇文章中的數據集是小唯跨越3個概念和非常有限的數據集的實際概念,我反對在現實世界中運行數據在拼接結果時會產生極長的分隔字符串,特別是對於自由格式列(如描述)而言,要大得多。

損失方面

的雖然嘗試GROUP_CONCAT我很快就意識到,我無法理解如何在相關GROUP_CONCAT列中的各種數據元素的情況下。我可以證明,通過使用例如書以上。

SPARQL

PREFIX p: <http://www.test.com/ontologies/property#> 

select ?authorfirstname 
     ?authorLastName 
     (group_concat(distinct ?bookname; separator = ";") as ?booknames) 
     (group_concat(distinct ?retailername; separator = ";") as ?retailernames) 
where { 
    ?author p:firstName ?authorfirstname; 
      p:lastName ?authorLastName; 
      p:hasWritten ?book . 
    OPTIONAL { 
     ?book p:name ?bookname; 
       p:soldBy ?retailer . 
     ?retailer p:name ?retailername . 
    } 
} 
group by ?authorfirstname ?authorLastName 

這將產生以下輸出;

firstname = "John" 
lastname = "Grisham" 
booknames = "The Client;The Firm" 
retailernames = "Amazon;Waterstones;Foyles" 

正如你可以看到這已經產生了一個結果行你不能再製定出各種數據元素是如何關聯。哪些零售商爲哪本書?

任何幫助/指導將不勝感激。

目前的解決方案

基於推薦的解決方案下面我用鑰匙的概念帶來的各種數據togehter設置但是我稍微tweeked它讓我使用的每個概念的查詢(例如作者,書籍和零售商),然後使用這些鍵將結果彙總到我的渲染器中。

作者結果

    firstname lastname books 
     -------------------------------------------------------------------------------- 
     1   John  Grisham ontologies/Book/TheClient|ontologies/Book/TheFirm 

圖書搜索結果

    id      name  retailers 
     ------------------------------------------------------------------------------------------------------- 
     1   ontologies/Book/TheClient The Client ontologies/Retailer/WaterStones|ontologies/Retailer/Amazon 
     2   ontologies/Book/TheFirm The Firm  ontologies/Retailer/WaterStones|ontologies/Retailer/Foyles 

零售商結果

    id        name 
     -------------------------------------------------- 
     1   ontologies/Retailer/Amazon  Amazon 
     2   ontologies/Retailer/Waterstones Waterstones 
     3   ontologies/Retailer/Foyles  Foyles 

然後我在渲染器中做的是使用ID從各種結果集中提取結果...

for-each author a : authors 
    output(a.firstname) 
    for-each book b : a.books.split("|") 
    book = books.get(b) // get the result for book b (e.g. Id to Foreign key) 
     output(book.name) 
     for-each retailer r : book.retailers.split("|") 
     retailer = retailers.get(r) 
     output(retailer.name) 

如此有效地將各種不同的結果集合並呈現出來,從而將所需要的東西拼接在一起。

這似乎是行得通的。

+0

與SPARQL唯一的直接方式是使用'GROUP_CONCAT'是你已經想通了。但是我沒有看到這裏的問題 - 好的,你必須爲所有可能具有同一實體的多個值的變量執行此操作,但這聽起來不太複雜。在你的例子中,它只是零售商。 – AKSW

+0

謝謝你的迴應。 當我嘗試使用GROUP_CONCAT函數時,我會用我的發現更新我的主要帖子,並且認爲這是一個不好的選擇。 –

回答

0

我發現在代碼中構造SPARQL結果中的對象更容易,而不是試圖形成一個查詢,該查詢只返回每個相關資源的單個行。

我將使用資源的URI來標識哪些行屬於哪個資源(本例中爲author),然後根據所述URI合併結果行。

對於JS應用程序,我使用代碼here從SPARQL結果中構造對象。

對於複雜的值,我在變量名中使用__來表示應該從該值構造一個對象。例如,變量前綴爲?book__的所有值都將變成一個對象,其中包含變量名稱的其餘部分作爲對象屬性的名稱,每個對象由?book__id標識。因此,具有?book__id?book__name的值將導致作者的屬性book,例如author.book = { id: '<book-uri>', name: 'book name'}(或者如果存在多本書的話這樣的對象的列表)。

例如,在這種情況下,我會使用以下查詢:

PREFIX p: <http://www.test.com/ontologies/property#> 

SELECT ?id ?firstName ?lastName ?book__id ?book__name 
     ?book__retailer 
WHERE { 
    ?id p:firstName ?firstName; 
      p:lastName ?lastName; 
      p:hasWritten ?book__id . 
    OPTIONAL { 
     ?book__id p:name ?book__name; 
      p:soldBy/p:name ?book__retailer . 
    } 
} 

並在應用程序代碼中,我將構建一個看起來像這樣(JavaScript的符號)作者的對象:

[{ 
    id: '<http://www.test.com/ontologies/Author/JohnGrisham>', 
    firstName: 'John', 
    lastName: 'Grisham', 
    book: [ 
     { 
      id: '<http://www.test.com/ontologies/Book/TheFirm>', 
      name: 'The Firm', 
      retailer: ['Amazon', 'Waterstones', 'Foyles'] 
     }, 
     { 
      id: '<http://www.test.com/ontologies/Book/TheClient>', 
      name: 'The Client', 
      retailer: ['Amazon', 'Waterstones', 'Foyles'] 
     } 
    ] 
}] 
+0

謝謝你的回答,我決定按照你的方法輕微的一週,因爲我正在爲每個概念運行一個單獨的查詢。 我將用我目前的解決方案更新主文章。 –

0

這是一個常見的問題,可以打擊任何關係數據庫,我想。正如你所說的GROUP_CONCAT在許多情況下是有用的,但確實失去了保真度。

我想出了一個您可能會感興趣的解決方案。假設您想要通過作者構建一個視圖或結果樹循環,然後爲每個作者創建他們的書籍,然後爲每個作者創建零售商。

SELECT DISTINCT ?authorname ?bookname ?retailername { 
    ... 
} ORDER BY ?authorname ?bookname ?retailername 

這讓你的結果是這樣的:

  author  book  retailer 
      ----------------------------- 
1   author1 book1 retailer1 
2   author1 book1 retailer2 
3   author1 book2 retailer2 
4   author2 book3 retailer2 
5   author2 book3 retailer3 
      ... 

由於訂貨有可能步

get next result 
currentauthor = author in result 

print currentauthor 

while author in next result = currentauthor: 
    get next result 
    currentbook = book in result 
    print currentauthor 
    while book in next result = currentbook: 
     get next result 
     print retailer in result