Удаление нежелательных ответов суперкласса в SPARQL

У меня есть файл OWL, который включает в себя таксономическую иерархию, в которую я хочу написать запрос, в котором ответ включает каждого человека и его непосредственного таксономического родителя. Вот пример (полный запрос довольно сложный).

@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix rdf: <http:://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix : <urn:ex:> .

:fido rdf:type :Dog .
:Dog rdfs:subClassOf :Mammal .
:Mammal rdfs:subClassOf :Vertebrate .
:Vertebrate rdfs:subClassOf :Animal .
:fido :hasToy :bone

:kitty rdf:type :Cat .
:Cat rdfs:subClassOf :Mammal .
:kitty :hasToy :catnipMouse .

И этот запрос делает то, что я хочу.

prefix rdf: <http:://www.w3.org/1999/02/22-rdf-syntax-ns#> .
prefix : <urn:ex:> .

SELECT ?individual ?type 
WHERE {
   ?individual :hasToy :bone .
   ?individual rdf:type ?type .
}

Проблема в том, что я предпочел бы использовать аргументированную версию файла OWL, которая неудивительно, что включает в себя дополнительные утверждения:

:fido rdf:type :Mammal .
:fido rdf:type :Vertebrate .
:fido rdf:type :Animal .
:kitty rdf:type :Mammal .
:kitty rdf:type :Vertebrate .
:kitty rdf:type :Animal .

И теперь запрос приводит к дополнительным ответам о том, что Fido является млекопитающим, и т. Д. Я мог бы просто отказаться от использования аргументированной версии файла, или, поскольку запросы SPARQL вызываются из Java, я мог бы выполнить несколько дополнительных запросов к найти наименее включенный тип, который появляется. Мой вопрос заключается в том, существует ли разумное решение SPARQL для возврата только решения Dog.

1 ответ

Решение

Общее решение заключается в том, что вы просите указать только прямой тип. Класс C это прямой тип экземпляра X если:

  1. X имеет тип C
  2. здесь нет C' такой что:
    • X имеет тип C'
    • C' это подкласс C
    • C' не равно C

(это последнее условие необходимо, кстати, потому что в RDF/OWL отношение подкласса является рефлексивным: каждый класс является подклассом сам по себе)

В SPARQL это выглядит примерно так:

PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX : <urn:ex:> .

SELECT ?individual ?type 
WHERE {
   ?individual :hasToy :bone .
   ?individual a ?type .
   FILTER NOT EXISTS { ?individual a ?other .
                       ?other rdfs:subClassOf ?type .
                       FILTER(?other != ?type)
   }
}

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

TupleQuery query = conn.prepareTupleQuery(SPARQL, "SELECT ...");
query.setIncludeInferred(false); 

TupleQueryResult result = query.evaluate();

Sesame также предлагает дополнительный дополнительный механизм вывода (называемый "непосредственным средством определения типа"), который вводит дополнительные "виртуальные" свойства, которые вы можете запрашивать, например: sesame:directType, sesame:directSubClassOf и т.д. Другие инструменты, несомненно, будут иметь аналогичные параметры.

Другие вопросы по тегам