Запросы по внутренним объектам

From Wiki4Intranet
Jump to: navigation, search

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
}}

Конечно, и про запросы, и про внутренние объекты можно рассказать и многое другое, но во-первых, сейчас не буду, а во-вторых, сам ещё не всё знаю :)