#sparql #rdf
Вопрос:
Учитывая конкретный узел http://my.org/nodes#n1
в базе данных RDF, я хотел бы получить все узлы, с которыми связаны n1
(с помощью множества предикатов), а затем снова — если возможно — получить все узлы, которые подключены к этим узлам.
Например, приведен следующий график о лицах и с кем они дружат:
@prefix p: <http://helloworld.org/person#> .
@prefix r: <http://helloworld.org/relation#> .
@prefix l: <http://helloworld.org/location#> .
l:l1 l:city "Sydney" .
l:l2 l:city "Paris" .
l:l3 l:city "New York" .
p:p1
p:name "Jack" ;
p:age 30 ;
p:livingIn l:l1 .
p:p2
p:name "Peter" ;
p:age 31 ;
p:livingIn l:l1 .
p:p3
p:name "Carol" ;
p:age 32 ;
p:livingIn l:l1 .
p:p4
p:name "Anna" ;
p:age 33 ;
p:livingIn l:l2 .
p:p5
p:name "Chris" ;
p:age 34 ;
p:livingIn l:l3 .
p:p1
r:isFriendOf p:p2 ;
r:isFriendOf p:p3 .
p:p3 r:isFriendOf p:p4 .
p:p4 r:isFriendOf p:p5 .
Я знаю, что между узлами существует только одна связь ( isFriendOf
), и, следовательно, легко запрашивать Jack
друзей и их друзей
PREFIX p: <http://helloworld.org/person#>
PREFIX r: <http://helloworld.org/relation#>
SELECT ?name ?friend ?foaf
WHERE {
?p r:isFriendOf ?o .
?p p:name ?name .
?o p:name ?friend .
OPTIONAL {
?o r:isFriendOf ?fo .
?fo p:name ?foaf
}
FILTER ( ?p = p:p1 )
}
Имя | друг | пенопласт |
---|---|---|
«Джек» | «Питер» | |
«Джек» | «Кэрол» | «Анна» |
Однако для гораздо более сложных графиков со многими взаимосвязями я изо всех сил пытаюсь получить результат. Я начал с
PREFIX id: <http://my.org/graph#>
SELECT ?s ?p ?o ?oo
WHERE {
?s ?p ?o .
OPTIONAL { ?o ?p ?oo . } # if an object has connections, get those as well
FILTER( ?s = id:12345 ) # id:12345 is the node we focus on
}
но эта { ?o ?p ?oo }
часть мне ничего не дает..
Ответ №1:
Узел, по которому вы выполняете фильтрацию (идентификатор:12345), не существует на опубликованном вами графике.
Запрос, который вы используете, имеет две проблемы: 1) вы ограничиваете свойство между интересующим вас ресурсом (id:12345) и объектом (o), который должен совпадать с объектом между ?o и ?o, 2) запрос неэффективен, так как вы извлекаете полный график, чтобы затем отфильтровать по интересующему узлу. Вместо этого вы могли бы сделать что-то вроде:
PREFIX id: <http://my.org/graph#>
SELECT ?s ?p ?o ?p1 ?oo
WHERE {
id:12345 ?p ?o .
OPTIONAL { ?o ?p1 ?oo . }
}
Если вам нужен пример, попробуйте следующее в https://dbpedia.org/sparql
select ?p ?o ?p1 ?oo where{
<http://dbpedia.org/resource/Madrid> ?p ?o
optional {?o ?p1 ?oo}
}
Первый результат выглядит примерно так:
p o p1 oo
http://www.w3.org/1999/02/22-rdf-syntax-ns#type http://dbpedia.org/ontology/Place http://www.w3.org/1999/02/22-rdf-syntax-ns#type http://www.w3.org/2002/07/owl#Class
Что имеет смысл: Мадрид-это место, а место-это класс.
Обратите внимание, что при этом отображаются только исходящие ссылки, а не входящие ссылки на интересующий узел. Для этого вам придется сделать что-то вроде:
select ?s1 ?p1 ?s ?p where{
?s ?p <http://dbpedia.org/resource/Madrid>
optional {?s1 ?p1 ?s}
}