Как рекурсивно развернуть пустые узлы в запросе конструкции SPARQL? - PullRequest
11 голосов
/ 20 марта 2012

Возможно, на этот вопрос легко ответить, но я даже не могу понять, как сформулировать запрос Google, чтобы найти его.

Я пишу запросы конструкции SPARQL к набору данных, который содержит пустоеузлы.Поэтому, если я сделаю запрос типа

CONSTRUCT {?x ?y ?z .} WHERE {?x ?y ?z .}

, то один из моих результатов может быть:

nm:John nm:owns _:Node

Что является проблемой, есливсе тройки

_:Node nm:has nm:Hats

также не попадают в результат запроса каким-либо образом (поскольку некоторые парсеры, которые я использую как rdflib для Python, действительно не любят висячие узлы).

Можно ли написать свой исходный запрос CONSTRUCT, чтобы рекурсивно добавить все тройки, присоединенные к любым результатам bnode, чтобы в моем новом графике не оставалось никаких bnodes?

Ответы [ 3 ]

11 голосов
/ 20 марта 2012

Рекурсия невозможна.Самое близкое, что я могу придумать, это пути к свойствам SPARQL 1.1 (обратите внимание: эта версия устарела), но тесты bnode недоступны (afaik).

Вы можете просто удалить операторыс конечными узлами:

CONSTRUCT {?x ?y ?z .} WHERE 
{
  ?x ?y ?z .
  FILTER (!isBlank(?z))
}

или попытайте счастья, выбрав следующий бит:

CONSTRUCT {?x ?y ?z . ?z ?w ?v } WHERE 
{
  ?x ?y ?z .
  OPTIONAL {
    ?z ?w ?v
    FILTER (isBlank(?z) && !isBlank(?v))
  }
}

(этот последний запрос довольно карательный, кстати)

Возможно, вылучше с DESCRIBE, который часто пропускает bnodes.

3 голосов
/ 20 марта 2012

Как предполагает пользователь 205512, рекурсивное выполнение этого захвата невозможно, и, как они указывают, использование необязательных (ых) уровней для перехода на произвольные уровни в ваших данных, получение узлов не представляется возможным ни для чего, кроме баз данных нетривиального размера.

Сами Bnodes имеют локальную область видимости, к набору результатов или к файлу.Нет никакой гарантии, что BNode вы получите при разборе или из набора результатов - это тот же идентификатор, который используется в базе данных (хотя некоторые базы данных гарантируют это для результатов запроса).Кроме того, запрос типа "select? S where {? S? P _: bnodeid1}" такой же, как "select? Where {? S? P? O}" "- обратите внимание, что в этом случае bnode обрабатывается как переменная, а не как "вещь с идентификатором 'bnodeid1'". Эта особенность дизайна затрудняет запрос на bnodes, поэтому, если вы контролируете данные, я бы посоветовал не использовать их.Нетрудно сгенерировать имена для вещей, которые в противном случае были бы bnodes, и именованные ресурсы v. Bnodes не будут увеличивать накладные расходы во время запросов.

Это не поможет вам восстановить и получить данные, но для этого я нене рекомендую делать такие общие запросы;они плохо масштабируются и обычно возвращают больше, чем вы хотите или нуждаетесь.Я бы посоветовал вам делать более направленные запросы.Ваш исходный запрос на конструкцию будет опускать содержимое всей базы данных, как правило, это не то, что вам нужно

Наконец, описание может быть полезным, но стандартной реализации нет;спецификация SPARQL не определяет какого-либо конкретного поведения, поэтому то, что она возвращает, остается за поставщиком базы данных, и оно может быть другим.Это может сделать ваш код менее переносимым, если вы планируете использовать разные базы данных с вашим приложением.Если вы хотите, чтобы конкретное поведение не описывалось, лучше всего реализовать его самостоятельно.Выполнение чего-то вроде краткого ограниченного описания ресурса является простым фрагментом кода, хотя вы можете столкнуться с некоторыми головными болями вокруг Bnodes.

1 голос
/ 21 февраля 2015

Что касается работы с библиотекой ruby ​​RDF.rb, которая позволяет выполнять запросы SPARQL со значительными удобными методами для объектов RDF :: Graph, то следующие должны расширять пустые узлы.

rdf_type = RDF::SCHEMA.Person # for example
rdf.query([nil, RDF.type, rdf_type]).each_subject do |subject|
  g = RDF::Graph.new
  rdf.query([subject, nil, nil]) do |s,p,o|
    g << [s,p,o]
    g << rdf_expand_blank_nodes(o) if o.node?
  end
end

def rdf_expand_blank_nodes(object)
  g = RDF::Graph.new
  if object.node?
    rdf.query([object, nil, nil]) do |s,p,o|
      g << [s,p,o]
      g << rdf_expand_blank_nodes(o) if o.node?
    end
  end
  g
end
...