Запросы по внутренним объектам
Semantic Internal Objects — расширение для Semantic MediaWiki, упрощающее описание N-арных отношений, которые в Semantic MediaWiki всегда моделируются на бинарных.
Бинарное отношение — это «объект, отношение, субъект». То есть «объект относится к субъекту так-то», например, «5 августа» (объект) есть дата рождения (отношение) Доктора Зойдберга (субъекта).
N-арное отношение — это «N объектов соотносятся друг с другом», например, «Вася Пупкин (человек — объект 1) работал в (отношение) компании Спортмастер (компания — объект 2), и руководителем у него был Иван Ходун (руководитель — объект 3)». Тут мы не можем сказать, что компания Васи Пупкина всегда Спортмастер, не можем сказать, что его руководитель — всегда Иван Ходун, и не можем сказать, что у всех, кто работает в Спортмастере, руководитель — Иван Ходун.
Создание внутренних объектов
Но в SMW n-арных отношений нет, и их нужно моделировать. Идея Internal Objects такая — создаётся объект «Вася Пупкин, работавший в Спортмастере» (или же «работа Васи Пупкина»), к нему прицепляется «Вася Пупкин» бинарным отношением «основной человек этого объекта» (внимание — как раз это название является первым аргументом функции {{#set_internal:}}, можно назвать, например, «Работник»), и к нему же прицепляются все свойства работы — компания, начальник и любые другие характеристики (например, период работы, должность). И компания «Васи Пупкина, работавшего в Спортмастере», всегда «Спортмастер», равно как и прочие атрибуты — то есть ура, мы смоделировали n-арное отношение.
Задаётся вся эта радость с помощью следующего синтаксиса на странице «Васи Пупкина» (функция парсера set_internal):
{{#set_internal:Работник |Компания=Спортмастер |Руководитель=Иван Ходун }}
Сам сгенерированный внутренний объект (Internal Object) будет иметь название «Вася Пупкин#1». Обратите внимание, что если перейти по такой ссылке, вы попадёте просто на страницу Васи Пупкина, так как #1 воспримется просто как Anchor-ссылка (ссылка на раздел).
Вывода никакого эта функция не генерирует. Чтобы сделать покрасивше, а также не забыть все атрибуты, эту фиговину можно запихнуть в шаблон (например «Шаблон:Работал в») — написать там:
<includeonly>{{#set_internal:Работник |Компания={{{1|}}} |Руководитель={{{2|}}} }}</includeonly> Работал в компании [[{{{1}}}]], руководителем был [[{{{2}}}]].
После этого на страницу Васи Пупкина можно писать просто {{Работал в|Спортмастер|Иван Ходун}} — выглядеть будет как «Работал в компании Спортмастер, руководителем был Иван Ходун».
Запросы в SMW
Вообще запросы в SMW можно делать с помощью функции парсера {{#ask: }} или со спецстраницы Special:Ask, которая представляет из себя простой интерфейсик к той же функции парсера.
- Поиск по значению свойства — {{#ask: [[Компания::Спортмастер]]}}. Найти все объекты, свойство «Компания» которых имеет значение «Спортмастер».
- Любое значение — {{#ask: [[Компания::+]]}}. Найти все объекты, имеющие свойство «Компания».
- Поиск по категории — {{#ask: [[Категория:Люди]]}}. Выбрать все объекты из категории «Люди».
- Подзапрос — {{#ask: [[Руководитель::<q>[[Категория:Люди]]</q>]]}}. Выбрать все объекты, свойство «Руководитель» которых ссылается на объект, входящий в категорию «Люди» (а не инопланетяне).
- Вывод в виде таблицы — {{#ask: ... | format=table | ?Поле = Заголовок колонки }} (прочие свойства можно посмотреть на Special:Ask)
И ещё одна важная вещь — инвертированный поиск по свойству (не «искомое относится к заданному», а «заданное относится к искомому»):
- {{#ask: [[-Дата рождения::Вася Пупкин]]}} — выбрать все даты рождения Васи Пупкина.
Маленькие заметки о том, чего SMW не умеет (по крайней мере, без хаков) — чтобы вы внезапно не тратили на выяснение этого время сами:
- Рекурсивные запросы во всю глубину. Есть только хак с подстановкой шаблона, вызывающего себя, в параметры функции ask.
- Отрицание категорий и страниц, то есть, найти объекты не в категории или исключить из результата заданную страницу.
Запросы по внутренним объектам
Итак, нагрузившись этим знанием, спросим себя: а как же теперь искать по свойствам внутренних объектов?
Ответ простой: ко всему запросу {{#ask: [[Компания::Спортмастер]]}} нужно добавить условие наличия свойства, заданного первым аргументом {{#set_internal: }} — выглядеть будет так:
{{#ask: [[Компания::Спортмастер]] [[Работник::+]]}}
Причём, вспоминая то, что наше свойство «Работник» ссылается на реального человека, вместо «+» можно подставить какой-нибудь подзапрос. Например:
{{#ask: [[Работник::<q>[[Категория:Люди]]</q>]] [[Компания::Спортмастер]] }}
Но теперь мы хотим поискать, например, людей, знакомых с этими людьми. Ну мы же помним, что есть подзапросы — берём и тупо пишем:
[[знаком с::<q> {{#ask: [[Работник::<q>[[Категория:Люди]]</q>]] [[Компания::Спортмастер]] }} </q>]]
А работать такой запрос не будет!
И даже вот такой (ещё более простой) запрос тоже не заработает: {{#ask: [[знаком с::<q>[[Работник::+]]</q>]] }}
Причина в том, что запрос [[Работник:: ... ]] возвращает внутренние объекты — например Иванов Иван Иванович#1. А нам нужны сами люди, например просто Иванов Иван Иванович. То есть, по сути, при запросах по внутренним объектам нужно всё время помнить, с чем вы работаете в текущей части запроса — с реальным объектом или с внутренним, и «именовать/разыменовывать» их при необходимости.
Для преобразования внутренних объектов в людей нужно использовать инвертированный поиск по свойству:
{{#ask: [[знаком с::<q>[[-Работник::<q>[[Работник::+]]</q>]]</q>]] }}
А вот пример ещё более сложного запроса (выбрать людей, знакомых с работниками Спортмастера):
{{#ask: <!-- "Компания" — свойство Internal Object'а, поэтому снова надо "именовать" - выбрать те internal object'ы, которые ссылаются на выбранные реальные объекты (людей) --> [[Работник::<q> <!-- "Знаком с" работает с реальными объектами людей --> [[знаком с::<q> <!-- Внутренний запрос возвращает Internal Object — "разыменовываем" его в сам объект --> [[-Работник::<q> <!-- "Работает" ссылается на любую страницу (и это может быть только человек) --> [[Работник::+]] [[Компания::Спортмастер]] </q>]] </q>]] </q>]] |?Работник=ФИО |?Должность |?Компания |?Отдел |mainlabel=- |format=table }}
Конечно, и про запросы, и про внутренние объекты можно рассказать и многое другое, но во-первых, сейчас не буду, а во-вторых, сам ещё не всё знаю :)