
Больше года назад Google объявил, что отныне в их поиске используется таинственная Сеть Знаний (официальный перевод Knowledge Graph). Возможно, не все знают, что значительная часть данных Сети доступна для использования всеми желающими и доступна по прекрасно описанному API. Этой частью является база знаний Freebase, поддерживаемая Google и энтузиастами. В этой статье мы сначала немного подурачимся, а потом попробуем сделать несколько простеньких запросов на языке MQL.
Эта статья — вторая из цикла Базы знаний. Следите за обновлениями.
- Часть 1 — Введение
- Часть 2 — Freebase: делаем запросы к Google Knowledge Graph
- Часть 3 — Dbpedia — ядро мира Linked Data
- Часть 4 — Wikidata — семантическая википедия
Google Knowledge Graph с точки зрения рядового пользователя
Одним из видимых проявлений Google Knowledge Graph являются информационные панели, кратко описывающие тот объект, который вы ищете. Они часто возникают при поиске персоналий, чуть реже — географических наименований. Они чаще возникают для запросов, заданных на английском языке в английском интерфейсе, но мы будем придерживаться русского языка там, где это возможно.
Например, запрос Роджер Уотерс даёт следующий результат:

Покликайте по ссылкам в инфобоксе и обратите внимание на URL — в нем используется параметр stick, содержимым которого является некоторый идентификатор вида &stick=H4sIAAAAAAAAAONg[VuLQz9U3]<сам идентификатор>AAAA
Когда Knowledge Graph только появился, это позволяло демонстрировать непосвященным небольшую уличную магию, например, добавлять &stick-параметр от Мерилин Монро к запросу от Стивена Кинга:

Сейчас такую возможность прикрыли, да и ни к чему она нам — лучше посмотрим на что-нибудь полезное. К примеру, недавно появилась возможность сравнить несколько объектов с помощью ключевого слова vs:

Гугл обещает добавить еще много вкусностей, связанных с умным поиском и ответами на вопросы, и Knowledge Graph будет одним из столпов, на котором эта интеллектуальность держится. Что особенно прекрасно для нас, так это то, что кусочек Knowledge Graph’a открыт для использования всеми желающими.
Freebase — подграф GNG
Начнем с исторического экскурса. Компания Metaweb начала работу над своей базой знаний в 2005 году. По способу наполнения данными Freebase больше всего походила на Dbpedia: львиную долю знаний, представленных во Freebase, являлись данные из Википедии. Отличием от Dbpedia была, во-первых, возможность поправлять введенные данные вручную, а во-вторых то, что Freebase не гнушалась и другими источниками данных. В отличии от команды DBpedia, представители Metaweb не слишком заботились о том, чтобы публиковать научные статьи (хотя в последнее время начали, вот тут интересный список), и признавались, что код основного компонента, graphd, вряд ли когда-нибудь увидит свет дня.
В 2010 году компания Metaweb была куплена Google, но, судя по рассылке Freebase, поисковый гигант не слишком вмешивался в дела свежеприобритенной команды. После выпуска красочного ролика, в котором Google рвет конкурентов, как пионерскую правду с помощью своих новых интеллектуальных семантических технологий, представители Metaweb (а затем и Google) подтвердили, что Freebase является очень важной частью Сети Знаний, наряду с Википедией и базой фактов ЦРУ. Во время большого субботника по унификации всех гугловых API, программный интерфейс Freebase сильным изменениям подвергать не стали, а его описание просто перенесли на developers.google.com. Для того, чтобы спросить что-нибудь у базы знаний мы по-прежнему используем язык запросов MQL (произн. «микл», Metaweb Query Language). За дело!
Первый запрос и редактор
Начнем с простенького вопроса: спросим у Freebase какой-нибудь факт, например дату рождения Леонардо да Винчи:
https://www.googleapis.com/freebase/v1/mqlread?query={"/type/object/id":"/en/leonardo_da_vinci","/people/person/date_of_birth":null}
Получим вполне корректный результат:
{ "result": { "/type/object/id": "/en/leonardo_da_vinci", "/people/person/date_of_birth": "1452-04-15" } }
Для того, чтобы нам было проще упражняться, мы будем использовать редактор запросов, любезно предоставляемый Freebase.

Редактор этот страшно удобен и имеет прекрасную функцию автодополнения запросов — в случае затруднений просто нажмите Ctrl+Enter и вы получите отличные контекстные подсказки. В нижней панели редактора расположились полезные инструменты, которые подробно описаны в руководстве. При самостоятельном изучении особенно советуем поглядеть на кнопку examples, содержащую примеры запросов, проясняющим многие возможности MQL.
Ну что, вот наш запрос, а вот ответ на него:
| Запрос | Ответ |
|---|---|
|
|
Разберем этот запрос подробнее. Мы указали идентификатор объекта во Freebase с помощью термина id. Идентификаторы есть у всех объектов, а слово id является сокращением от /type/object/id. Есть много других /type/object свойств, которыми обладают все сущности Freebase, они будут рассмотрены чуть позже.
Объект, имеющий идентификатор /en/leonardo_da_vinci, возможно, обладает свойством /people/person/date_of_birth, значения которого мы не знаем. Мы ставим вместо этого значения специальное слово null, на место которого в ответе Freebase запишет значение из базы.
Как легко заметить, запрос и ответ на него симметричны.
Сложный запрос
Теперь, для того, чтобы возникло побольше вопросов, мы составим достаточно сложный MQL-запрос и вкратце его объясним. После этого можно будет приступить к подробному изучению структуры Freebase и обзору возможностей языка.
Итак, вот наш запрос (взят из руководства по MQL):
| Запрос | Ответ |
|---|---|
|
|
Попробуем вкратце описать, что за средства MQL использованы в данном запросе.
Во-первых, как можно видеть, весь запрос обернут в конструкцию [ { } ], что означает, что в качестве результата вы ожидаете массив объектов, а не один объект, как в случае с { }.
Строки 2-4 не должны вызывать каких-либо проблем: мы ищем объект типа альбом (/music/album), нам хочется получить его имя и нас не интересуют альбомы, называющиеся "Greatest Hits".
В строчках 5-8 и 11-15 появляется оператор ИЛИ |= — нас интересуют альбомы, у которых дата выхода равна 1978 или 1979 году. Перейдем теперь к жанру:
"genre":[],
"a:genre": "New Wave",
"b:genre|=": [
"Punk Rock",
"Post-punk",
"Progressive rock"
],
Первая строчка говорит о том, что нам хочется получить список жанров данных альбомов в ответе запроса. Для этого мы добавили в запрос пустой список [ ]. Дальше мы говорим, что нас интересуют только альбомы, в жанрах которых указаны New Wave И один из списка «Punk Rock», «Post-punk», «Progressive rock».
Наконец, строки 23-24 содержат директивы MQL: мне интересны только два результата (limit) и я хочу отсортировать их по имени (sort).
JSON в MQL
MQL-запросы и ответы на них являются JSON-объектами, поэтому для самых маленьких (или тех, кто не относится к веб-разработчикам) расскажу о JSON.
Самый простой JSON-объект — пустой объект. Он записывается следующим образом:
{}
Теперь давайте создадим объект, в котором хранится информация о Леонардо да Винчи. Для начала ограничимся только его именем. Для этого заключим ключ и значение в кавычки, разделив двоеточием
{ "name" : "Leonardo di ser Piero da Vinci" }
Добавляем несколько фактов о Леонардо, разделяя их через запятую:
{ "name" : "Leonardo di ser Piero da Vinci", "date_of_birth": "1453-04-15", }
Теперь стоит определить, что за профессия была у да Винчи. А профессий-то этих было много: и скульптор, и художник, и архитектор и еще много кто. Для того, чтобы присвоить одному ключу несколько значений, в JSON используются списки значений — заключенные в квадратные скобки значения, указанные через запятую:
{ "name" : "Leonardo di ser Piero da Vinci", "date_of_birth": "1453-04-15", "profession": [ "Architect", "Engineer", "Anatomist", "Inventor", "Artist", "Sculptor" ], }
Еще одна вещь о JSON, которую стоит знать, — это вложенные объекты. Они делаются крайне просто: после ключа вы просто вставляете новый набор пар ключей-значений в фигурных скобках. В случае с Леонардо мы можем попробовать отобразить данные о месте рождения Леонардо — селе Анкиано, находящемся в Италии. Мы скажем, что ключ «place_of_birth» соответствует некоторому объекту с именем Anchiano, находящимся в Italy:
{ "name" : "Leonardo di ser Piero da Vinci", "date_of_birth": "1453-04-15", "profession": [ "Architect", "Engineer", "Anatomist", "Inventor", "Artist", "Sculptor" ], "place_of_birth": { "name": "Anchiano", "containedby": "Italy", }, }
Не совсем JSON
Вообще, MQL-запросы не являются корректными JSON-объектами. MQL — это надмножество JSON и в нём разрешаются разного рода вольности. Одна из идей продуктов Metaweb заключается в том, что программы должны уметь прощать пользователям ошибки и описки, которые те делают. Эта идея есть и в других языках и программах, а в первую очередь — в World Wide Web — ничего страшного, что некоторые части html написаны с ошибками, нужно все равно постараться отобразить документ.
Вот, например, корректный JSON-запрос, ищущий людей с редкой и ценной профессией:
{ "id": "/en/pope", "/people/profession/people_with_this_profession": [{ "name": null, "limit": 4 }] }
Мы можем убрать кавычки и запрос продолжит работать:
{ id: /en/pope, /people/profession/people_with_this_profession: [{ name: null, limit: 4 }] }
Закрывать скобочки и разделять пары двоеточием тоже не обязательно, так что вот пример совсем уж безобразия:
id /en/pope /people/profession/people_with_this_profession [{ name null limit 4
Устройство Freebase
Официальное руководство дает очень хорошее введение в то, как хранятся данные внутри Freebase. Нам это не слишком важно, потому что используемые во Freebase четверки объектов полностью скрыты за объектной парадигмой. Если вам интересно, можете обратиться к соответствующей странице мануала
Итак, Freebase позволяет нам думать о том, что внутри него лежат объекты. Каждый объект ограничивается фигурными скобками { } и состоит из пар «свойство-значение», разделенных двоеточиями. Объекты, которые Freebase выдает в качестве ответов на MQL-запросы, являются корректными JSON-объектами, однако они не похожи на объекты парадигмы ООП. Лучше всего думать о них, как о неупорядоченных множествах пар.
В качестве свойства (то есть того, что стоит до двоеточия) в MQL могут стоять идентификаторы. В качестве значений могут быть идентификаторы, литералы, массивы и, наконец, вложенные объекты.Freebase имеет правила, по которым должны строиться идентификаторы. Идентификатор состоит из пространства имен и ключа, разделенных прямым слэшем /. Рассмотрим, например, идентификатор /people/person/date_of_birth — в нем date_of_birth является ключом, а /people/person — пространством имен.
Идентификаторы уникальны. Они не обязаны нести смысловой нагрузки, однако зачастую по идентификатору объекта легко понять, о чем идет речь.
Универсальные свойства объектов
Все объекты Freebase обладают следующими зарезервированными (универсальными свойствами):
- имя —
/type/object/name - ключ —
/type/object/key - идентификатор —
/type/object/id - тип (обычно больше одного) —
/type/object/type - время создания —
/type/object/timestamp - создатель —
/type/object/creator - режим доступа —
/type/object/permission - глобальный идентификатор —
/type/object/guid - машинный идентификатор —
/type/object/mid
Мы рассмотрим тут свойства, которые наиболее часто используются в MQL-запросах: имена, идентификаторы и типы.
Идентификаторы
Во Freebase как-то очень много идентификаторов. Самый главный из них /type/object/guid, даётся раз и навсегда. Есть его сокращенная форма /type/object/mid. Ну а пользуются в запросах обычно /type/object/id — он часто бывает человекочитабельным. Самое главное, это то, что не бывает двух объектов с одинаковыми идентификаторами. Так например, взгляните, как многих людей звали Адам Смит (Adam Smith): статья на английской Википедии. Только моральный философ Адам Смит носит гордый идентификатор /en/adam_smith. Все остальные Адамы Смиты будут идентифицироваться по другому, будь они политиками (/en/adam_smith_1965), футболистами (/en/adam_smith_huddersfield) или кем-либо другим.
Вы можете ввести идентификатор в поле поиска на Freebase.com и получить страницу свойств объекта:

Свойство /type/object/name
У каждого объекта есть имя. Имя — вещь не уникальная, у объекта обычно несколько имен — по одному на каждый язык. Самое интересное, что это нисколько не усложняет запросы — вы заметите, что при запросе имен вам будет выдаваться только имя на языке, установленном во Freebase как текущий. Так что можно обращаться с объектами типа name как с обычными строками.
Свойство /type/object/type
Это свойство задает тип объекта. У одного объекта может быть несколько типов — обычно так и бывает.
Если в запросе вы указали свойство type, то вы пространство имен для этого типа можно опускать. Какие свойства относятся к типу /film/director? Разумеется, те, которые находятся в пространстве имен этого типа, то есть те, что начинаются с /film/director. Рассмотрим, например, запрос всех фильмов, снятых Стэнли Кубриком. Слева показан запрос в сокращенной форме, которой мы и будем пользоваться дальше, а справа — то, как он мог бы выглядеть, не будь разработчики Metaweb так добры к нам.
| Запрос | Запрос в полной форме |
|---|---|
|
|
Во-вторых, все свойства из пространства имен /type/object можно опускать — именно поэтому мы имеет право писать просто id, name, type и т.д. Почему? Потому что все объекты в Freebase имеют тип Объект.
Различные виды MQL-запросов
Мы уже разобрали довольно много запросов, но пока не сосредотачивались на самом языке. В первую очередь, давайте посмотрим на то, как в MQL запрашиваются нужные значения. Бывают следующие случаи:
- мне нужно запросить одно литеральное значение. Например, дату рождения человека
- мне нужно запросить массив значений. Например список альбомов музыкальной группы.
- мне нужно запросить один объект c его основными свойствами: идентификатором, основным типом и именем
- мне нужно запросить массив объектов
- мне нужно узнать всё об объекте
Запрос одного значения
Если вы хотите, чтобы Freebase вернул вам объект той же структуры, что и объект запроса, но с заполненным неизвестным полем, то в запросе надо вместо этого поля подставить null. Мы видели довольно много таких примеров, вот вам еще один. Спросим у музыканта Кита Эмерсона, откуда он родом:
| Запрос | Ответ |
|---|---|
|
|
Запрос массива значений
Если мы попробуем использовать null для запроса всех альбомов музыкальной группы, то мы получим ошибку. Если вы ожидаете массив объектов, используйте квадратные скобки []. Freebase заполнит этот массив строками, перечисленными через запятую. Примеров с альбомами музкалььных групп полно и в официальном руководстве, а мы найдем список книжек, написанных Хокингом:
| Запрос | Ответ |
|---|---|
|
Там еще много
|
Если вы напротив, запросите массив вместо одиночного значения – в этот нет никаких проблем – Freebase преобразует результаты и выдаст массив с одним-единственным значением.
Запрос объектов
Хорошо, но для моего приложения мне интересно знать не только названия книжек Хокинга, но и даты их выхода, и картиночки бы не помешали! Такое тоже возможно. Дело в том, что массив книг, который мы получили в прошлом запросе, только выглядит массивом строк. На самом деле, это массив объектов, просто Freebase сворачивает объекты в строки, оставляя только их свойство name.
Также и Англия, откуда родом наш музыкант, это не просто строка «England», а полноценный объект. Чтобы получить объектное представление в запросе, используется конструкция { }, вот так:
{ "name": "Keith Emerson", "type": "/music/artist", "origin": { } }
В результате нам выдадут самую важную информацию об объекте: его идентификатор, название и список типов:
{ "result": { "origin": { "id": "/en/england", "name": "England", "type": [ "/common/topic", "/location/location", "/film/film_subject", "/book/book_subject", "/location/administrative_division", "/film/film_location", "/location/uk_constituent_country", "/user/xleioo/winning_night/option_list", "/location/statistical_region", "/location/dated_location", "/symbols/name_source", "/m/04kp2w0", "/user/robert/military/military_power", "/symbols/flag_referent", "/user/skud/flags/topic", "/user/skud/names/topic", "/user/robert/military/topic", "/base/petbreeds/topic", "/m/04mp17s", "/user/xleioo/winning_night/topic", "/organization/organization_scope", "/base/charities/geographic_scope", "/sports/sports_team_location", "/base/thoroughbredracing/thoroughbred_racehorse_origin", "/user/tsegaran/random/taxonomy_subject", "/base/authors/country_of_origin", "/base/authors/topic", "/biology/breed_origin", "/fictional_universe/fictional_setting", "/government/political_district", "/olympics/olympic_participating_country", "/base/summermovies2009/topic", "/base/leicester/topic", "/base/popstra/location", "/location/country", "/base/england/topic", "/base/ontologies/ontology_instance", "/event/speech_topic", "/user/skud/legal/treaty_signatory", "/government/governmental_jurisdiction", "/base/masterthesis/topic", "/user/jamie/default_domain/yacht_racing/yacht_racing_country", "/base/horticulture/cultivar_origin", "/base/horticulture/topic", "/base/localfood/food_producing_region", "/base/localfood/topic", "/sports/sport_country", "/base/todolists/topic", "/base/tagit/concept", "/food/beer_country_region", "/periodicals/newspaper_circulation_area", "/location/uk_statistical_location", "/base/biblioness/bibs_location", "/base/biblioness/bibs_topic", "/base/aareas/schema/gb/constituent_country", "/base/aareas/schema/administrative_area", "/base/uncommon/topic", "/base/schemastaging/statistical_region_extra", "/people/place_of_interment", "/base/allthingsnewyork/topic", "/base/events/topic", "/base/events/geographical_scope", "/base/tonyfranksbuckley/topic", "/base/piratesofthewirralpeninsula/topic", "/military/military_combatant", "/military/military_post", "/organization/organization_member" ] }, "name": "Keith Emerson", "type": "/music/artist" } }
Вложенные запросы
Можно получить любую другую информацию о стране происхождения нашего музыканта, формируя, таким образом, вложенный запрос. Например, мне хочется узнать, на каком языке говорят в стране, откуда родом Эмерсон. Обратите внимание, я добавляю тип для страны, чтобы получать подсказки от редактора запросов:
| Запрос | Ответ |
|---|---|
|
|
Можно спуститься ниже: к какой языковой семье относится язык, на котором говорят в стране, откуда родом Эмерсон?
| Запрос | Ответ |
|---|---|
|
|
Эти довольно дурацкие запросы легко обобщаются в нечто более полезное. Например, запрос на получение списка музыкантов, родом из англоговорящих стран. Обратите внимание, что я часто использую вывод в виде массива. Ну и еще на слово limit, которое ограничивает вывод тремя результатами:
| Запрос | Ответ |
|---|---|
|
|
Запрос всех свойств объекта
Полезная вещь при конструировании запроса — получить все свойства объекта. Конструкция, используемая для этого очень проста и удобна: звездочка в качестве названия свойства и пустой массив, который заполнится значениями "*" : []
| Запрос | Ответ |
|---|---|
|
У Англии много свойств
|
Как лучше запрашивать объекты
Для тех, кто успел запутаться в скобочках, вот сводка по тому, как во Freebase можно запрашивать объекты:
| Конструкция | Её смысл |
|---|---|
|
запрашивается значение свойства в виде одной строка. В качетсве этой строки будет выдано значение default-свойства объекта: value (для литералов) или name (для объектов). Если значением свойства является массив, выдается ошибка! |
|
запрашивается массив строк. Результатом может быть пустой, массив, массив с одним значением или массив с несколькими значениями |
|
на каждое свойство объекта запрашивается массив его значений |
|
запрашивается краткая информация об объекте. Для обычных объектов выдается их имя, идентификатор и тип |
|
запрашивается массив объектов в кратком виде. Работает аналогично {}, но для массивов |
|
у объекта-значения свойства спрашивается все, что указано в запросе |
|
вложенный запрос относится ко всем объектам в массиве значений свойств. Действует аналогично предыдущему для массивов. |
Для начала достаточно. Понятное дело, что в MQL есть различные компараторы, регулярные выражения, всякие там И, ИЛИ и НЕ. Еще прекрасен язык Acre, который позволяет форматировать результаты запросов подобно тому, как это делается в Semantic MediaWiki. Ну и впереди рассказ о Dbpedia и Wikidata. Что бы вам было интересно почитать в первую очередь?
ссылка на оригинал статьи http://habrahabr.ru/post/177217/
Добавить комментарий