2015-04-09 6 views
2

Несколько лет назад я изучил некоторые семантические технологии, включая RDF и SPARQL, после чего у меня не было шансов работать с ними некоторое время. Теперь я начал новый проект, который использует OpenRDF 2.8.0 в качестве семантического хранилища, и я возобновляю свои знания, хотя у меня есть некоторые забытые вещи для восстановления.О UNION и FILTER NOT EXISTS в SPARQL (OpenRDF 2.8.0)

В частности, в прошлые дни у меня возникли проблемы с правильной деинсталляцией конструкции FILTER NOT EXIST в SPARQL.

Проблема: у меня есть семантический магазин, импортированный из DbTune.org (он-томы музыки). mo:MusicArtist, задумана как foaf:maker из более mo:Track, может присутствовать в четырех сценариев (я только листинг соответствующие заявления):

<http://dbtune.org/musicbrainz/resource/artist/013c8e5b-d72a-4cd3-8dee-6c64d6125823> a mo:MusicArtist ; 
     vocab:artist_type "1"^^xs:short ; 
     rdfs:label "Edvard Grieg" . 

    <http://dbtune.org/musicbrainz/resource/artist/032df978-9130-490e-8857-0c9ef231fae8> a mo:MusicArtist ; 
     vocab:artist_type "2"^^xs:short ; 
     rel:collaboratesWith <http://dbtune.org/musicbrainz/resource/artist/3db5dfb1-1b91-4038-8268-ae04d15b6a3e> , <http://dbtune.org/musicbrainz/resource/artist/d78afc01-f918-440c-89fc-9d546a3ba4ac> ; 
     rdfs:label "Doris Day & Howard Keel". 

    <http://dbtune.org/musicbrainz/resource/artist/1645f335-2367-427d-8e2d-ad206946a8eb> a mo:MusicArtist ; 
     vocab:artist_type "2"^^xs:short ; 
     rdfs:label "Pat Metheny & Anna Maria Jopek". 

    <http://dbtune.org/musicbrainz/resource/artist/12822d4f-4607-4f1d-ab16-d6bacc27cafe> a mo:MusicArtist ; 
     rdfs:label "René Marie". 

Из того, что я понимаю, vocab:artist_type является 1 для отдельных художников (пример # 1) и 2 для групп сотрудничества (примеры № 2 и № 3). В этом случае может быть несколько операторов rel:collaboratesWith, которые указывают на описание отдельных членов группы или совместной работы (пример № 2). В некоторых случаях отсутствует инструкция vocab:artist_type (пример № 4).

Теперь я хочу извлечь всех художников как единичные объекты, где это возможно. Я имею в виду, я не хочу извлекать пример №2, потому что я получу «Дорис Дэй» и «Говард Кил» отдельно. Мне нужно извлечь пример № 3 «Pat Metheny & Anna Maria Jopek», потому что я ничего не могу сделать. Конечно, я также хочу получить «Рене Мари».

Я решил эту проблему удовлетворительным образом с этим SPARQL:

SELECT * 
    WHERE 
     { 
     ?artist  a   mo:MusicArtist. 
     ?artist  rdfs:label ?label. 

     MINUS 
      { 
      ?artist  vocab:artist_type  "2"^^xs:short. 
      ?artist  rel:collaboratesWith ?any1 . 
      } 
     } 
    ORDER BY ?label 

Это имеет смысл, и это выглядит, как будто это читаемое («извлечь все mo:MusicArtist элементов минус тех, которые сотрудничество с отдельными членами перечисленных»).

Я не нашел решение немедленно. Я сначала подумал, укладывание три отдельных случаев, с UNION:

SELECT * 
    WHERE 
     { 
     ?artist  a     mo:MusicArtist. 
     ?artist  rdfs:label  ?label. 
    # Single artists 
      { 
      ?artist  vocab:artist_type  "1"^^xs:short. 
      } 
     UNION 
    # Groups for which there is no defined collaboration with single persons 
      { 
      ?artist  vocab:artist_type  "2"^^xs:short. 
      FILTER NOT EXISTS 
       { 
       ?artist  rel:collaboratesWith ?any1 
       } 
      } 
     UNION 
    # Some artists don't have this attribute 
      { 
      FILTER NOT EXISTS 
       { 
       ?artist  vocab:artist_type  ?any2 
       } 
      } 
     } 
    ORDER BY ?label 

Я обнаружил, что третьи UNION заявления, те, которые должны добавить mo:MusicArtist элементов без vocab:artist_type, не работало. То есть, они не нашли такие предметы, как «Рене Мари».

В то время как я удовлетворен самым коротким решением, которое я нашел с MINUS, я не согласен с тем, что не понимаю, почему старое решение не сработало. Ясно, что я пропустил какой-то момент с FILTER NOT EXISTS, который может быть полезен для другого случая.

Любая помощь приветствуется.

+0

Один из ваших комментариев говорит «Группы, для которых не существует определенного сотрудничества с отдельными лицами» --- там должен быть какой-либо проверки, что сотрудник (значение? Any1) на самом деле один человек, т. е. не группа? –

+0

Joshua, хорошо вопрос. Я не видел групп, связанных с группами, в данных, связанных с моей музыкальной коллекцией, но, конечно, я не исследовал весь репозиторий. Я думаю, это не имеет значения. Идея состоит в том, что если есть rel: collaborationWith это может быть что угодно, и в конечном итоге цепочка сотрудничества, будет конечный элемент, который больше не связан ни с чем. –

ответ

3

Когда я запускаю следующий запрос, я получаю результаты, что это звучит, как вы ищете:

select distinct ?label where { 
    ?artist a mo:MusicArtist ; 
      rdfs:label ?label . 

    #-- artists with type 1 
    { 
    ?artist vocab:artist_type "1"^^xs:short 
    } 
    #-- artists with no type 
    union { 
    filter not exists { 
     ?artist vocab:artist_type ?type 
    } 
    } 
    #-- artists with type 2 that have no 
    #-- collaborators 
    union { 
    ?artist vocab:artist_type "2"^^xs:short 
    filter not exists { 
     ?artist rel:collaboratesWith ?another 
    } 
    } 
} 

------------------------------------ 
| label       | 
==================================== 
| "René Marie"      | 
| "Pat Metheny & Anna Maria Jopek" | 
| "Edvard Grieg"     | 
------------------------------------ 

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

select ?label where { 
    #-- get an artist and their label 
    ?artist a mo:MusicArtist ; 
      rdfs:label ?label . 

    #-- and optionally their type, if it is 
    #-- "1"^^xs:short or "2"^^xs:short 
    optional { 
    values ?type { "1"^^xs:short "2"^^xs:short } 
    ?artist vocab:artist_type ?type 
    } 

    #-- if ?type is "2"^^xs:short, then ?artist 
    #-- must not collaborate with anyone. 
    filter (!sameTerm(?type,"2"^^xs:short) 
     || not exists { ?artist rel:collaboratesWith ?anyone }) 
} 

------------------------------------ 
| label       | 
==================================== 
| "René Marie"      | 
| "Pat Metheny & Anna Maria Jopek" | 
| "Edvard Grieg"     | 
------------------------------------ 
+0

Спасибо за подсказку, я изучаю ее. Кстати, я еще не рассматривал проблемы с производительностью. Я полагаю, что разные запросы, которые производят одни и те же результаты, могут выполняться по-разному. Несколько лет назад я знал о некоторых вещах, которых можно было избежать, но после такого долгого времени я думаю, что все могло измениться. Есть ли какая-нибудь конструкция, которая, как известно, медленна? Конечно, я имею в виду реализацию OpenRDF. –

+0

@FabrizioGiudici Я думаю, что состояние оптимизации запросов для SPARQL не так развито, как некоторые реляционные базы данных, и есть немного больше различий между системами. Лично я бы не стал слишком беспокоиться о производительности, пока вы не узнаете, что-то является узким местом или нет. –

+0

@ Josuha. Это имеет смысл. Благодарю. –

 Смежные вопросы

  • Нет связанных вопросов^_^