У меня есть таблицы в моей базе данных mySQL, например:
+-------+------------+-------------+-----------+ | 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 | +-------+------------+-------------+-----------+
Для Predicate subClassof
него будет такое дерево:
Main |__ Network | |__ ATM | |__ ARPANET | |__ Software |__ Linux |__ Windows |__ XP |__ Win7 |__ Win8
Я хочу создать форму, которая может выбрать начальный узел и получить для него всех родителей. Например, выбрав Win7
я хочу получить:
main, Software, Windows,
Win7
Шаг 2: есть ли способ распечатать эти узлы с помощью простого текста следующим образом:
Main |__ Software |__ Windows |__ Win7
Ваши данные могут быть представлены в RDF как 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 .
Отсюда вам просто нужен запрос SPARQL, который находит все вещи, связанные с определенным классом, путем пути (включая пустой путь) свойств rdfs:subClassOf
.
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 | --------------
Результаты этого запроса не обязательно упорядочиваются по их позиции на пути (хотя в этом случае они случаются). Если они вам понадобятся, вы можете сделать это (на основе этого ответа о вычислении позиции элементов в списке RDF ):
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)
Это находит каждый ?class
предок :Win7
а также каждый ?mid
промежуточный предк. Для ?class
precestor расстояние вычисляется как число промежуточных отношений между ними ( count(?mid)
). Он заказывает результаты на основе этого расстояния, поэтому :Win7
является ближайшим предком :Windows
после этого и так далее.
Вы даже можете сделать некоторые из фантазии форматирования вы хотите, как это:
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" | -----------------------------------
Возможно, потребуется выполнить некоторую строчную обработку и получить многострочную строку. Вы можете взглянуть на последнюю часть этого ответа, где есть какое-то причудливое форматирование для хорошо выровненной матрицы идей.