Перейти к основному содержимому

SPARQL

Этот документ был подготовлен при помощи ИИ

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

SPARQL обращается к модели как к RDF. Это один из двух языков, изменяющих модель: запрос читает, SPARQL Update пишет, поэтому на SPARQL можно написать тело быстрого исправления.

Запрос на SPARQL в консоли и ответ на него: по строке на каждое выбранное имя

Как пишется выражение

Выражение на SPARQL — это одна законченная операция SPARQL: запрос или обновление. Модель, которой принадлежит контекстный объект, отображается в RDF, выражение выполняется над ней, а сам объект привязан к ?self.

Правило формулирует вопрос о ?self, на который отвечают «да» или «нет»:

ASK { ?self archimate:Nameable.name ?name . FILTER(STRLEN(STR(?name)) > 0) }

Строки PREFIX писать не нужно. Стандартные префиксы rdf, rdfs, owl и xsd уже объявлены, как и по одному префиксу на каждую доступную метамодель — он берётся из собственного префикса метамодели, archimate для ArchiMate. Свои префиксы объявлять по-прежнему можно; объявление в теле имеет приоритет.

Автодополнение предлагает переменные, уже использованные в теле, классы и свойства доступных метамоделей, а также ключевые слова SPARQL. После переменной в позиции предиката оно сначала предлагает свойства.

Формы запроса и их результат

ФормаРезультат
ASKлогическое значение
SELECTодна строка на решение
CONSTRUCTтриплеты, которые порождает шаблон
DESCRIBEтриплеты, описывающие указанные ресурсы

SELECT с одной проецируемой переменной возвращает сами значения. Если значение — это IRI объекта, вы получаете объект и можете по нему перейти. SELECT с несколькими проецируемыми переменными даёт на каждое решение одну строку из пар имя=значение.

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

Видимые переменные

?self — объект, для которого вычисляется выражение; он привязан к своему IRI. Какой это объект, зависит от того, где выражение выполняется, — см. Консоль выражений.

В обновлении дополнительно привязывается ?g — граф с моделью. Остальные переменные тела вы привязываете сами.

RDF-представление модели

Выражение видит только ту модель, которой принадлежит ?self. Внутри неё:

  • объект — это IRI вида urn:uuid:<id>;
  • ?o a archimate:BusinessActor сопоставляется с конкретным классом объекта и только с ним — надтипы триплетов не порождают, поэтому шаблон для archimate:ArchimateElement не сопоставляется ни с чем;
  • характеристика адресуется как prefix:DeclaringClass.feature, поэтому имя бизнес-актора — это archimate:Nameable.name, а концы отношения — archimate:ArchimateRelationship.source и archimate:ArchimateRelationship.target;
  • атрибут — это литерал, хранящий значение в строковой форме, включая числа, логические значения и литералы перечислений, поэтому сравнивайте через STR() и приводите через xsd:integer() и подобные, когда нужно число;
  • ссылка — это триплет, объектом которого является IRI цели, а вложение — такая же ссылка, как любая другая, поэтому archimate:Folder.elements и archimate:FolderContainer.folders обходят дерево модели;
  • триплеты порождают только заданные характеристики; производные и транзиентные не дают ничего — incomingRelationships и outgoingRelationships транзиентны, поэтому добирайтесь до отношения через source и target;
  • обратная ссылка — это шаблон с переменной в позиции объекта: ?subject ?property ?self находит всё, что указывает на ?self.

Отображение целиком описано в Модели как RDF.

В запросе триплеты находятся в графе по умолчанию, поэтому конструкция GRAPH не нужна и ни с чем не сопоставляется.

Изменение модели

Тело обновления описывает изменение, которое выполнит быстрое исправление. Триплеты модели находятся в графе ?g, и читается потом только он, поэтому все шаблоны и образцы, работающие с моделью, помещайте внутрь GRAPH ?g:

DELETE { GRAPH ?g { ?self archimate:Nameable.name ?name } }
INSERT { GRAPH ?g { ?self archimate:Nameable.name ?trimmed } }
WHERE { GRAPH ?g { ?self archimate:Nameable.name ?name }
BIND(REPLACE(STR(?name), "^\\s+|\\s+$", "") AS ?trimmed) }

INSERT DATA и DELETE DATA не принимают переменных вообще, поэтому ?self и ?g в них не подставить. Пишите вместо этого INSERT { GRAPH ?g { ... } } WHERE { ... }.

Несколько операций, разделённых ;, выполняются по порядку над одним и тем же графом, и ?self и ?g остаются привязанными во всех них.

К модели применяется разница между графом до обновления и после него:

  • добавление или удаление триплета атрибута устанавливает или сбрасывает атрибут;
  • добавление или удаление триплета ссылки связывает или развязывает два объекта;
  • триплет rdf:type с новым IRI в субъекте создаёт объект этого класса, а ссылка вложения присоединяет его к модели. IRI выдаёт BIND(UUID() AS ?new). Класс должен быть конкретным;
  • удаление триплета ссылки вложения, удерживающего объект, отсоединяет его от модели.

Добавление, указывающее на несуществующий объект, отмечается как предупреждение и не применяется.

Изменяющее тело порождает набор отдельных изменений. Режим применения задаёт, попадут ли они в модель сразу или будут ждать поштучного подтверждения. См. Консоль выражений.

Примеры

Чтение, где ?self — элемент ArchiMate.

У элемента есть имя:

ASK { ?self archimate:Nameable.name ?name . FILTER(STRLEN(STR(?name)) > 0) }

Элемент с чем-нибудь связан:

ASK {
{ ?r archimate:ArchimateRelationship.source ?self }
UNION
{ ?r archimate:ArchimateRelationship.target ?self }
}

У элемента ровно одно свойство owner:

ASK {
{ SELECT (COUNT(?p) AS ?owners) WHERE {
?self archimate:Properties.properties ?p .
?p archimate:Property.key "owner" .
} }
FILTER(?owners = 1)
}

Документированный элемент должен быть и именованным:

ASK {
FILTER NOT EXISTS {
?self archimate:Documentable.documentation ?doc .
FILTER(STRLEN(STR(?doc)) > 0)
FILTER NOT EXISTS { ?self archimate:Nameable.name ?name .
FILTER(STRLEN(STR(?name)) > 0) }
}
}

Имена следуют соглашению:

ASK {
?self archimate:Nameable.name ?name .
FILTER(REGEX(STR(?name), "^[A-Z][A-Za-z ]*$"))
}

Всё, что реализует этот элемент:

SELECT ?target WHERE {
?r a archimate:RealizationRelationship ;
archimate:ArchimateRelationship.source ?self ;
archimate:ArchimateRelationship.target ?target .
}

Всё, что указывает на этот элемент:

SELECT ?subject ?property WHERE { ?subject ?property ?self }

Всё, до чего можно дойти от этого элемента по отношениям вперёд:

SELECT DISTINCT ?reached WHERE {
?self (^archimate:ArchimateRelationship.source/archimate:ArchimateRelationship.target)+ ?reached
}

Элементы, лежащие в папке, которых не касается ни одно отношение:

SELECT ?element WHERE {
?folder archimate:Folder.elements ?element .
FILTER NOT EXISTS { ?r archimate:ArchimateRelationship.source ?element }
FILTER NOT EXISTS { ?r archimate:ArchimateRelationship.target ?element }
}

Сколько объектов каждого класса содержит модель:

SELECT ?class (COUNT(?object) AS ?count) WHERE { ?object a ?class }
GROUP BY ?class
ORDER BY DESC(?count)

Изменение, где ?self — элемент ArchiMate.

Задать элементу свойство owner, если его нет:

INSERT { GRAPH ?g { ?self archimate:Properties.properties ?new .
?new a archimate:Property ;
archimate:Property.key "owner" ;
archimate:Property.value "unassigned" } }
WHERE { BIND(UUID() AS ?new)
FILTER NOT EXISTS { GRAPH ?g {
?self archimate:Properties.properties ?p .
?p archimate:Property.key "owner" } } }

Подставить заглушку документации, когда её нет:

INSERT { GRAPH ?g { ?self archimate:Documentable.documentation "To be documented" } }
WHERE { FILTER NOT EXISTS { GRAPH ?g {
?self archimate:Documentable.documentation ?doc } } }

Отсоединить элемент и всё, что на него ссылается:

DELETE WHERE { GRAPH ?g { ?self ?p ?o } } ;
DELETE WHERE { GRAPH ?g { ?s ?r ?self } }

Справочник по SPARQL

Принимается полная грамматика SPARQL 1.1 Query и Update, а поверх неё — триплетные термы RDF-star, поддерживаемые движком запросов.

Формы запроса

СинтаксисВозвращаетЗначение
SELECT ?a ?b WHERE { ... }строкиперечисленные переменные, по строке на решение
SELECT * WHERE { ... }строкивсе переменные, использованные в образце
SELECT (expr AS ?v) WHERE { ... }строкивычисленное значение под новым именем
SELECT DISTINCT ...строкидубликаты решений удалены
SELECT REDUCED ...строкидубликаты могут быть удалены
ASK { ... }логическоеесть ли у образца хотя бы одно решение
CONSTRUCT { ... } WHERE { ... }триплетышаблон, инстанцированный для каждого решения
CONSTRUCT WHERE { ... }триплетысам образец в роли шаблона
DESCRIBE ?v WHERE { ... }триплетыописание каждого связанного ресурса
DESCRIBE <iri>триплетыописание указанного ресурса

Формы обновления

СинтаксисЗначение
INSERT DATA { GRAPH <g> { ... } }добавить перечисленные триплеты; переменные не допускаются, поэтому ?self и ?g использовать нельзя
DELETE DATA { GRAPH <g> { ... } }удалить перечисленные триплеты; переменные не допускаются
INSERT { ... } WHERE { ... }добавить шаблон по разу на решение
DELETE { ... } WHERE { ... }удалить шаблон по разу на решение
DELETE { ... } INSERT { ... } WHERE { ... }удалить и добавить в одной операции
DELETE WHERE { ... }удалить ровно то, что сопоставилось с образцом
WITH <g> DELETE { ... } INSERT { ... } WHERE { ... }назвать целевой граф один раз для всей операции
USING <g>построить граф, который читает предложение WHERE
USING NAMED <g>сделать граф адресуемым через GRAPH в предложении WHERE
LOAD <url> / LOAD <url> INTO GRAPH <g>прочитать RDF-документ по URL в граф
LOAD SILENT <url>то же, но без ошибки, если документ прочитать не удалось
CLEAR GRAPH <g> / CLEAR DEFAULT / CLEAR NAMED / CLEAR ALLудалить все триплеты из графов
DROP GRAPH <g> / DROP DEFAULT / DROP NAMED / DROP ALLудалить графы
CREATE GRAPH <g>создать пустой граф
ADD <g1> TO <g2>скопировать триплеты одного графа в другой
COPY <g1> TO <g2>заменить содержимое графа содержимым другого
MOVE <g1> TO <g2>как COPY, затем удалить исходный граф
<op> ; <op>выполнить операции последовательно

CLEAR, DROP, CREATE, ADD, COPY и MOVE называют графы по IRI и нигде не принимают ?g, поэтому нацелить их на граф модели нельзя. Триплеты, записанные не в ?g, по завершении обновления отбрасываются.

Пролог и набор данных

СинтаксисЗначение
PREFIX p: <namespace>привязать префикс CURIE
BASE <iri>задать базу для относительных IRI
FROM <g>построить граф по умолчанию из перечисленных именованных графов
FROM NAMED <g>сделать граф адресуемым через GRAPH

Запрос читает модель из графа по умолчанию, поэтому конструкция FROM или FROM NAMED выбирает граф, которого у запроса нет.

Графовые образцы

СинтаксисЗначение
?s ?p ?o .триплетный образец
?s ?p ?o1, ?o2 .два объекта при одних субъекте и предикате
?s ?p1 ?o1 ; ?p2 ?o2 .два предиката при одном субъекте
?s a <Class>сокращение для rdf:type
{ ... }группа
GRAPH ?g { ... }сопоставление внутри именованного графа
OPTIONAL { ... }сопоставить, если возможно, иначе оставить переменные несвязанными
{ ... } UNION { ... }решения любой из сторон
MINUS { ... }отбросить решения, совместимые с правой стороной
FILTER(expr)оставить решения, для которых выражение истинно
FILTER EXISTS { ... }оставить решения, для которых образец сопоставляется
FILTER NOT EXISTS { ... }оставить решения, для которых он не сопоставляется
BIND(expr AS ?v)привязать вычисленное значение
VALUES ?v { "a" "b" }задать возможные значения одной переменной
VALUES (?a ?b) { ("x" 1) ("y" 2) }задать строки значений для нескольких переменных
VALUES (?a ?b) { ("x" UNDEF) }оставить переменную строки несвязанной
{ SELECT ... WHERE { ... } }подзапрос, вычисляемый первым
SERVICE <endpoint> { ... }передать образец удалённой точке SPARQL
SERVICE SILENT <endpoint> { ... }то же, но отказ удалённой точки игнорируется
[ ?p ?o ]пустой узел, описанный по месту
( ?a ?b )RDF-коллекция

Пути по свойствам

СинтаксисЗначение
iriодин шаг по свойству
^iriодин шаг назад — обратная ссылка
p1/p2последовательность шагов
p1|p2любой из путей
p*ноль или более шагов
p+один или более шагов
p?ноль или один шаг
!iriлюбое свойство, кроме этого
!(p1|p2)любое свойство вне набора
(p)группировка

Этот путь обходит граф отношений вперёд на любую глубину:

?self (^archimate:ArchimateRelationship.source/
archimate:ArchimateRelationship.target)+ ?reached

Модификаторы решений

СинтаксисЗначение
ORDER BY ?vсортировка по возрастанию значений переменной
ORDER BY ASC(expr), ORDER BY DESC(expr)сортировка по вычисленному ключу
GROUP BY ?vсгруппировать решения перед агрегированием
GROUP BY (expr AS ?v)группировка по вычисленному ключу
HAVING(expr)оставить группы, для которых выражение истинно
LIMIT nне более n строк
OFFSET nпропустить первые n строк

Операторы

В порядке убывания приоритета.

СинтаксисВозвращаетЗначение
!a, +a, -aлогическое, числоотрицание, знак
a * b, a / bчислоумножение, деление
a + b, a - bчислосложение, вычитание
a = b, a != bлогическоеравенство и неравенство значений
a < b, a <= b, a > b, a >= bлогическоепорядок
a IN (x, y)логическоепринадлежность списку
a NOT IN (x, y)логическоеотсутствие в списке
a && bлогическоеконъюнкция
a || bлогическоедизъюнкция

Литералы и термы

СинтаксисЗначение
<http://example.org/x>абсолютный IRI
prefix:localCURIE относительно объявленного префикса
ardf:type
?v, $vпеременная
"text", 'text'строковый литерал
"""text""", '''text'''многострочный строковый литерал
"text"@enлитерал с языковым тегом
"5"^^xsd:integerлитерал с явным типом данных
42, -3целочисленный литерал
4.5десятичный литерал
1.0e6литерал двойной точности
true, falseлогический литерал
_:b1именованный пустой узел
[]анонимный пустой узел
()rdf:nil, пустая коллекция
# textкомментарий до конца строки
<<?s ?p ?o>>триплетный терм

Функции над термами, проверки и преобразования

СинтаксисВозвращаетЗначение
STR(term)строкалексическая форма литерала или IRI
LANG(literal)строкаязыковой тег, пустой, если его нет
LANGMATCHES(tag, range)логическоесоответствует ли языковой тег диапазону
DATATYPE(literal)IRIтип данных литерала
BOUND(?v)логическоеесть ли у переменной значение
IRI(string), URI(string)IRIпостроить IRI из строки
BNODE(), BNODE(string)пустой узелновый пустой узел
UUID()IRIновый IRI вида urn:uuid:
STRUUID()строкановый UUID в виде строки
isIRI(term), isURI(term)логическоеявляется ли терм IRI
isBLANK(term)логическоеявляется ли терм пустым узлом
isLITERAL(term)логическоеявляется ли терм литералом
isNUMERIC(term)логическоеявляется ли терм числовым литералом
sameTerm(a, b)логическоетождество термов, строже чем =
IF(cond, a, b)любоеусловное значение
COALESCE(a, b, ...)любоепервый аргумент, вычисляемый без ошибки
STRDT(string, iri)литераллитерал с заданным типом данных
STRLANG(string, tag)литераллитерал с заданным языковым тегом
xsd:string(v)литералприведение к строке
xsd:boolean(v)литералприведение к логическому значению
xsd:integer(v), xsd:decimal(v), xsd:double(v), xsd:float(v)литералприведение к числу
xsd:long(v), xsd:int(v), xsd:short(v), xsd:byte(v)литералприведение к целому заданного размера
xsd:unsignedLong(v), xsd:unsignedInt(v), xsd:unsignedShort(v), xsd:unsignedByte(v)литералприведение к беззнаковому целому
xsd:nonNegativeInteger(v), xsd:positiveInteger(v), xsd:nonPositiveInteger(v), xsd:negativeInteger(v)литералприведение к целому с ограничением знака
xsd:date(v), xsd:dateTime(v)литералприведение к дате или дате со временем

Строковые функции

СинтаксисВозвращаетЗначение
STRLEN(s)числоколичество символов
SUBSTR(s, start)строкаот позиции (с единицы) до конца
SUBSTR(s, start, length)строказаданное количество символов
UCASE(s), LCASE(s)строкасмена регистра
STRSTARTS(s, prefix)логическоеначинается ли строка с префикса
STRENDS(s, suffix)логическоезаканчивается ли строка суффиксом
CONTAINS(s, part)логическоесодержит ли строка фрагмент
STRBEFORE(s, part)строкачто предшествует первому вхождению
STRAFTER(s, part)строкачто следует за первым вхождением
ENCODE_FOR_URI(s)строкапроцентное кодирование для URI
CONCAT(s1, s2, ...)строкасоединить аргументы
REGEX(s, pattern)логическоесопоставляется ли шаблон
REGEX(s, pattern, flags)логическоето же, с флагами вроде "i"
REPLACE(s, pattern, replacement)строказаменить каждое совпадение
REPLACE(s, pattern, replacement, flags)строкато же, с флагами

STRAFTER(STR(?name), "-") возвращает то, что следует за первым дефисом имени.

Числовые функции

СинтаксисВозвращаетЗначение
ABS(n)числомодуль
ROUND(n)числоближайшее целое
CEIL(n)числонаименьшее целое, не меньшее n
FLOOR(n)числонаибольшее целое, не большее n
RAND()числочисло двойной точности от 0 до 1

Функции даты и времени

СинтаксисВозвращаетЗначение
NOW()dateTimeтекущие дата и время
YEAR(d), MONTH(d), DAY(d)числосоставляющие даты
HOURS(d), MINUTES(d), SECONDS(d)числосоставляющие времени
TIMEZONE(d)длительностьчасовой пояс как длительность
TZ(d)строкачасовой пояс в исходной записи

Хеш-функции

СинтаксисВозвращаетЗначение
MD5(s)строкадайджест MD5 в шестнадцатеричном виде
SHA1(s)строкадайджест SHA-1
SHA256(s)строкадайджест SHA-256
SHA384(s)строкадайджест SHA-384
SHA512(s)строкадайджест SHA-512

Функции над триплетными термами

Эти функции не имеют записи с ключевым словом. Каждая вызывается по своему IRI, который записывается через уже объявленный префикс rdf.

СинтаксисВозвращаетЗначение
rdf:Statement(s, p, o)триплетный термпостроить триплетный терм
rdf:isTriple(t)логическоеявляется ли терм триплетным термом
rdf:subject(t)термсубъект триплетного терма
rdf:predicate(t)IRIпредикат триплетного терма
rdf:object(t)термобъект триплетного терма

Агрегаты

СинтаксисВозвращаетЗначение
COUNT(?v)числоколичество связанных значений
COUNT(*)числоколичество решений в группе
COUNT(DISTINCT ?v)числоколичество различных значений
SUM(?v), AVG(?v)числосумма и среднее
MIN(?v), MAX(?v)любоенаименьшее и наибольшее значение
SAMPLE(?v)любоеодно значение из группы
GROUP_CONCAT(?v)строказначения, соединённые пробелом
GROUP_CONCAT(?v; SEPARATOR=", ")строказначения, соединённые заданным разделителем

DISTINCT можно написать внутри любого агрегата, например GROUP_CONCAT(DISTINCT ?name; SEPARATOR=", ").

Ещё четыре агрегата не имеют записи с ключевым словом и вызываются по IRI:

СинтаксисВозвращаетЗначение
<http://rdf4j.org/aggregate#stdev>(?v)числовыборочное стандартное отклонение
<http://rdf4j.org/aggregate#stdev_population>(?v)числостандартное отклонение генеральной совокупности
<http://rdf4j.org/aggregate#variance>(?v)числовыборочная дисперсия
<http://rdf4j.org/aggregate#variance_population>(?v)числодисперсия генеральной совокупности

Дополнительные материалы