Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SPARQL query to get all parent of a node

I have tables in my mySQL database like:

+-------+------------+-------------+-----------+
|  ID   |  subject   |  Predicate  |  object   |
+-------+------------+-------------+-----------+
|  1    | ATM        |  subClassof | Network   |
+-------+------------+-------------+-----------+
|  2    | ARPANET    |  subClassof | Network   |
+-------+------------+-------------+-----------+
|  3    | Network    |  subClassof | Main      |
+-------+------------+-------------+-----------+
|  5    | Software   |  subclassof | Main      |
+-------+------------+-------------+-----------+
|  7    | Linux      |  subClassof | Software  |
+-------+------------+-------------+-----------+
|  8    | Windows    |  subClassof | Software  |
+-------+------------+-------------+-----------+
|  12   | XP         |  subClassof | Windows   |
+-------+------------+-------------+-----------+
|  13   | Win7       |  subClassof | Windows   |
+-------+------------+-------------+-----------+
|  14   | Win8       |  subClassof | Windows   |
+-------+------------+-------------+-----------+

For Predicate subClassof it will have a tree view like this:

Main
   |__ Network
   |         |__ ATM
   |         |__ ARPANET
   |
   |__ Software
              |__ Linux
              |__ Windows
                        |__ XP
                        |__ Win7
                        |__ Win8

I want to create a form which can select the start node and get all parent for that. For example by choosing Win7 i want to get:

main, Software, Windows,Win7


Step2: is there any way to print this nodes with a simple text like this:

Main
   |__ Software
              |__ Windows
                        |__ Win7
like image 880
osyan Avatar asked Jul 31 '13 11:07

osyan


1 Answers

Your data can be represented in RDF as data.n3:

@prefix : <http://example.org/> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .

:Network rdfs:subClassOf :Main .

:ATM rdfs:subClassOf :Network .
:ARPANET rdfs:subClassOf :Network .

:Software rdfs:subClassOf :Main .

:Linux rdfs:subClassOf :Software .
:Windows rdfs:subClassOf :Software .

:XP rdfs:subClassOf :Windows .
:Win7 rdfs:subClassOf :Windows .
:Win8 rdfs:subClassOf :Windows .

From here, you just want a SPARQL query that finds all the things connected to a particular class by a path (including the empty path) of rdfs:subClassOf properties.

prefix : <http://example.org/>
prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>

select ?superclass where { 
  :Win7 rdfs:subClassOf* ?superclass
}
--------------
| superclass |
==============
| :Win7      |
| :Windows   |
| :Software  |
| :Main      |
--------------

The results in that query aren't necessarily ordered by their position in the path (though in this case they happen to be). If you do need them in order, you can do this (which is based on this answer about computing the position of elements in an RDF list):

prefix : <http://example.org/>
prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>

select ?class where { 
  :Win7 rdfs:subClassOf* ?mid .
  ?mid rdfs:subClassOf* ?class .
}
group by ?class
order by count(?mid)

This finds each ancestor ?class of :Win7 as well as each ?mid intermediate ancestor. For ancestor ?class, the distance is computed as the number of intermediate relations in between (count(?mid)). It orders the results based that distance, so :Win7 is the closest ancestor, :Windows after that, and so on.

You can even do some of the fancy formatting you want like this:

prefix : <http://example.org/>
prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>

select (group_concat( ?name ; separator="--" )  as ?path) where {
  {
    select ?name where { 
      :Win7 rdfs:subClassOf* ?mid .
      ?mid rdfs:subClassOf* ?class .
      bind( strAfter( str(?class), "http://example.org/") as ?name )
    }
    group by ?class ?name
    order by count(?mid)
  }
}
-----------------------------------
| path                            |
===================================
| "Win7--Windows--Software--Main" |
-----------------------------------

It might be possible to do some fancier string processing and to get the multiline string. You might look at the latter part of this answer where there is some fancy formatting for a nicely aligned matrix for ideas.

like image 54
Joshua Taylor Avatar answered Oct 03 '22 17:10

Joshua Taylor