SPARQL: выбор n-го пустого узла

Возьмите следующий график:

:Foo :p _:b0 ;
   :p _:b1 ;
   :p _:b2 .

_:b0 :p1 :apple ;
   :p2 :banana .

_:b1 :p3 :cantaloupe ;
   :p4 :date ;
   :p5 :elderberry .

_:b2 :p6 :fig .

Примечание. :Foo является подлежащим трех троек с одним и тем же предикатом :p. Объектом каждой из этих троек является пустой узел.


Можно ли написать запрос SPARQL, который выбирает все тройки, где только _:b1 является субъектом?


РЕДАКТИРОВАТЬ: Прежде чем предлагать ответ, поймите, что я ищу умное решение своего вопроса в SPARQL. Предположим, что тройное хранилище фиксировано (т. е. ничего нельзя сделать для изменения данных). График, показанный выше, надуман; каждый пустой узел не имеет одинакового количества троек p/o. Однако если бы у каждого из них было по одной тройке, то следующего SPARQL-запроса могло бы быть достаточно:

select ?b1 where {
   :Foo :p ?bn .
   ?bn ?p ?o
} limit 1 offset 1

Очевидно, проблема здесь в том, что каждый раз возвращается один и тот же пустой узел. Я знаю, что это набор и по своей сути неупорядоченный, поэтому повторяющийся порядок результатов не гарантируется; но, честно говоря... для фиксированного тройного хранилища я искренне сомневаюсь, что DFA вернет другой порядок пустых узлов между запросами. Есть умные идеи?


person Blake Regalia    schedule 29.09.2015    source источник


Ответы (1)


Вы не можете выбрать «n-й» пустой узел в SPARQL по двум причинам:

  1. модель RDF представляет собой множество: тройки неупорядочены.
  2. пустой узел представляет ресурс без идентификатора, что означает, что он не может быть (напрямую) адресован/идентифицирован.

В RDF/SPARQL вы работаете с пустыми узлами косвенным образом: вместо того, чтобы пытаться обращаться к ним напрямую (что, как мы видели выше, невозможно, поскольку само определение пустого узла состоит в том, что у него нет идентификатора), вы смотрите на вещи, которые связывают их с другими ресурсами, то есть заявления, в которых они участвуют. В конце концов, операторы придают пустому узлу его контекстуальное значение.

В вашем случае: различия между _:b1 и двумя другими пустыми узлами заключаются в утверждениях, в которых они играют роль субъекта. Таким образом, чтобы запросить в SPARQL триплеты, где _:b1 является субъектом, вы должны посмотреть на данные и увидеть, что _:b1 однозначно имеет свойство :p3 со значением :cantaloupe. Таким образом, вы можете запросить так:

   CONSTRUCT { ?s ?p ?o }
   WHERE { :Foo :p ?s .
           ?s :p3 :cantaloupe ;
              ?p ?o .
   }

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

Если вы обнаружите, что действительно не можете работать без прямого обращения к своим пустым узлам, вам следует подумать о том, чтобы вообще не использовать пустые узлы в своих данных, а вместо этого создать для этих вещей правильные IRI.

ОБНОВЛЕНИЕ Ваше обновление вопроса в основном спрашивает следующее: «Могу ли я использовать какую-то недокументированную функцию в неназванной конкретной реализации SPARQL для выполнения запроса, который, строго говоря, незаконен или не гарантированно даст желаемый результат и сойдет с рук?» Ответ на этот вопрос: вероятно, да, но это зависит от того, какую реализацию SPARQL вы используете, и это очень плохая идея по всем причинам, которые я привел выше.

Многие (большинство?) тройных хранилищ действительно дадут один и тот же результат в том же порядке между запросами на практике, хотя это не гарантируется (я не могу это подчеркнуть), и вам действительно не следует полагаться в теме. Конечно, вы можете получить упорядоченный результат запроса, используя предложение ORDER BY в своем запросе, но в данном случае это не поможет, поскольку относительный порядок пустых узлов не определен в SPARQL (поэтому механизм запросов может возвращать _:b1 и _:b2 в любом порядке, который он сочтет нужным, даже если есть пункт ORDER BY). Еще хуже: хотя ваш входной RDF-файл может содержать пустые идентификаторы узлов _:b1 и _:b2, это не обязательно то, что выдаст запрос SPARQL. Многие тройные хранилища заменяют пустые идентификаторы узлов внутренними идентификаторами, и ваш запрос SPARQL с такой же вероятностью вернет _:genid-908c909aeacc4b6da3d3059e18706d68-b1 вместо простого _:b1.

И даже если бы вы могли каким-то образом надежно вернуть пустой идентификатор узла: что вы собираетесь с ним делать? Пустой узел пуст. Идентификатор, который он несет, предназначен только для целей внутренней бухгалтерии - вы не можете использовать пустой узел для дальнейших запросов.

Поверьте мне: это плохая идея. Если вы не можете изменить данные, полагайтесь на свойства, которые соединяют пустые узлы и запрашивают их.

person Jeen Broekstra    schedule 30.09.2015
comment
Я знаю, вздох... но спасибо, что нашли время написать это для других. Я обновил свой вопрос. - person Blake Regalia; 30.09.2015