SPARQL-запрос для выбора / построения последней ревизии из данных RDF - PullRequest
4 голосов
/ 02 марта 2010

У меня есть RDF-файл, который используется для отслеживания изменений товара. Используя эти данные, я могу отслеживать изменения, внесенные в элемент в течение срока его службы. Как только конкретный объект изменился, соответствующие данные помещаются в новую редакцию. Посмотрите ..

@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix mymeta: <http://www.mymeta.com/meta/> .
@prefix dc: <http://purl.org/dc/elements/1.1/> .

<urn:ITEMID:12345> rdf:type mymeta:item .
<urn:ITEMID:12345> mymeta:itemchange <urn:ITEMID:12345:REV-1> .
<urn:ITEMID:12345:REV-1> dc:title "Product original name"@en .
<urn:ITEMID:12345:REV-1> dc:issued "2006-12-01"@en .
<urn:ITEMID:12345:REV-1> dc:format "4 x 6 x 1 in"@en .
<urn:ITEMID:12345:REV-1> dc:extent "200"@en .

<urn:ITEMID:12345> rdf:type mymeta:item .
<urn:ITEMID:12345> mymeta:itemchange <urn:ITEMID:12345:REV-2> .
<urn:ITEMID:12345:REV-2> dc:title "Improved Product Name"@en .
<urn:ITEMID:12345:REV-2> dc:issued "2007-06-01"@en .

Согласно этим данным, в «2007-06-01» была изменена позиция, в которой только имя элемента было изменено на «Улучшенное имя продукта». Как вы можете видеть, «dc: format» и «dc: экстент» отсутствуют в последней версии данных. Это сделано для того, чтобы избежать миллионов повторяющихся записей!

Я могу написать запрос SPARQL, который покажет мне последнюю информацию о версии продукта (REV-2: dc: title и dc: выпустил), но в нем отсутствуют "dc: format" и "dc: экстент", которые я хочу перенести с последней ревизии (REV-1).

Как мне написать SPARQL-запрос для этого? Любая помощь высоко ценится!

Ответы [ 3 ]

2 голосов
/ 10 марта 2010

Не уверен, что вы можете сделать это в одном запросе. Я подумаю об этом больше, если смогу, но следующие два запроса помогут вам начать в правильном направлении:

1) Найдите изменения, которые не имеют формата

PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX mymeta: <http://www.mymeta.com/meta/>
PREFIX dc: <http://purl.org/dc/elements/1.1/>

DESCRIBE ?change
WHERE 
{
    ?item a mymeta:item;
             mymeta:itemchange ?change.
    ?change ?p ?o.
    OPTIONAL 
    {
        ?change dc:format ?format .
    }
    FILTER (!bound(?format)) 
}

2) Я думаю, что это найдет самое старое изменение, которое имеет формат

PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX mymeta: <http://www.mymeta.com/meta/>
PREFIX dc: <http://purl.org/dc/elements/1.1/>

SELECT DISTINCT ?format
WHERE {
    ?item a mymeta:item;
             mymeta:itemchange ?change.
    ?change  dc:format ?format;
                  dc:issued ?issued.
    OPTIONAL {
        ?moreRecentItem a mymeta:item;
                ?moreRecentItem dc:issued ?moreRecentIssued.
        FILTER (?moreRecentIssued > ?issued)}
    FILTER (?bound (?moreRecentIssued))
}

Если проделать еще больше работы, то можно ограничить формат (2) тем, что он относится к изменениям с датой выпуска до данных выпуска результата (1). Поэтому для каждой строки из (1) вы должны выполнить (2), чтобы найти значение формата для использования. Вы могли бы получить лучшие результаты, если бы вы использовали механизм рассуждений на основе правил, а не SPARQL. Я бы порекомендовал EulerSharp или Pellet.

1 голос
/ 14 октября 2013

Для одного элемента это довольно простой запрос с использованием подзапросов SPARQL 1.1. Хитрость заключается в том, чтобы упорядочить ревизии, которые имеют данное свойство, по дате и взять значение из последней ревизии. Форма values используется только для указания элементов, которые вы выбираете. Если вам нужно запросить дополнительные элементы, вы можете добавить их в блок values.

prefix mymeta: <http://www.mymeta.com/meta/> 
prefix dc: <http://purl.org/dc/elements/1.1/> 

select ?item ?title ?format ?extent where {
  values ?item { <urn:ITEMID:12345> }

  #-- Get the title by examining all the revisions that specify a title, 
  #-- ordering them by date, and taking the latest one.  The same approach
  #-- is used for the format and extent.
  { select ?title { ?item mymeta:itemchange [ dc:title ?title ; dc:issued ?date ] . }
    order by desc(?date) limit 1 }

  { select ?format { ?item mymeta:itemchange [ dc:format ?format ; dc:issued ?date ] . }
    order by desc(?date) limit 1 }

  { select ?extent { ?item mymeta:itemchange [ dc:extent ?extent ; dc:issued ?date ] . }
    order by desc(?date) limit 1 }
}
$ sparql --data data.n3  --query query.rq
----------------------------------------------------------------------------------
| item               | title                      | format            | extent   |
==================================================================================
| <urn:ITEMID:12345> | "Improved Product Name"@en | "4 x 6 x 1 in"@en | "200"@en |
----------------------------------------------------------------------------------

Если вам действительно нужно сделать это для всех элементов, вы можете использовать другой подзапрос для выбора элементов. То есть вместо values ?item { ... } используйте:

{ select ?item { ?item a mymeta:item } }

Хотя это не было упомянуто в исходном вопросе, это в комментариях , если вы хотите получить самые последние значения свойств для всех свойств, вы можете выполнить подзапрос, как следующее, основанное на Как ограничить размер группы решений SPARQL?

select ?item ?property ?value {
  values ?item { <urn:ITEMID:12345> }

  ?item mymeta:itemchange [ ?property ?value ; dc:issued ?date ]

  #-- This subquery finds the earliest date for each property in
  #-- the graph for each item.  Then, outside the subquery, we 
  #-- retrieve the particular value associated with that date.  
  {
    select ?property (max(?date_) as ?date) {
      ?item mymeta:itemchange [ ?property [] ; dc:issued ?date_ ]
    }
    group by ?item ?property
  }
}
---------------------------------------------------------------
| item               | property  | value                      |
===============================================================
| <urn:ITEMID:12345> | dc:issued | "2007-06-01"@en            |
| <urn:ITEMID:12345> | dc:title  | "Improved Product Name"@en |
| <urn:ITEMID:12345> | dc:extent | "200"@en                   |
| <urn:ITEMID:12345> | dc:format | "4 x 6 x 1 in"@en          |
---------------------------------------------------------------
0 голосов
/ 09 июля 2013

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

Теория алгоритма вашего патча в настоящее время ошибочна, так как у вас нет метода определения последней ревизии, и вы не можете легко проследить ревизии, чтобы найти последний раз, когда произошла тройка. Кроме того, как вы узнаете, что тройка была законно удалена в ревизии, если вы всегда пытаетесь вернуться к предыдущим ревизиям, чтобы получить тройку, если вы не можете найти ее в самой последней ревизии?

База данных RDF должна быть в состоянии ограничить количество дублирования, сохраняя литералы и URI только один раз и используя указатели для создания тройных или четырехугольных чисел. Возможно, вы сможете заставить его работать в наивном случае, когда все хранится для каждой сохраняемой вами ревизии.

...