Pull to refresh

Работа с Freebase из .NET

Reading time3 min
Views3.3K
Недавно начал работать над проектом, который требует информацию о фильмах, музыке, книгах. Для этого необходимо наполнить базу данных из другого ресурса. Решил воспользоваться свободной базой данных Freebase.

Freebase — большая база знаний, содержащая структурированные данные, собранные из множества различных источников. На данный момент она насчитывает примерно 23 миллиона тем. Каждая тема ассоциирована с одним или несколькими типами (люди, места, фильмы).

Для получения данных из Freebase существует несколько вариантов:
  • Скачать dump базы данных (это можно сделать тут)
  • Использовать API

Постоянное восстановление из дампа отбросил сразу (хочется чего то более автоматизированного). Стал разбираться дальше. Для работы с API необходимо воспользоваться одним из 6 сервисов:
  • Search Service — поиск сущностей по ключевому слову;
  • Mql Read Service — извлечение детализированных данных о сущностях;
  • Topic Service — извлечение всей информации о сущности;
  • RDF Service — извлечение всей информации о сущности в RDF формате;
  • Text Service — извлечение короткого описания для сущности;
  • Image Service — получение картинки для сущности.

Первая задача которая передо мной стояла сделать autocomplete с использованием Freebase и последующей записью в свою базу данных. Для этой цели подходят два сервиса: Search Service и Mql Read Service. Выбрал второй так как с помощью него можно не только найти но и получить дополнительную информацию. Сразу же загуглил на предмет готовых либ (не люблю писать велосипеды). Все что удалось найти freebase-dotnet (использует старый API) и google-api-dotnet-client. Обе либы не реализуют асинхронных возможностей C#.

Поэтому вынужден был писать свою либу, которую можно найти здесь. Она пока ещё в бета версии, но по ходу текущего проекта я её дорабатываю и делаю стабильной, так как она будет использоваться в продакшине.

Прописав в nuget поиске Freebase4net, устанавливаем готовый package.

Чтобы пользоваться API нам надо получить ключ у Google (metaweb был куплен гуглом). Количество возможных запросов ограничено 100k запросов в день.

Для установки ApiKey мы можем сделать так
FreebaseServices.SetApiKey("YOUR API KEY");
либо так
<add key="FreebaseApiKey" value="AIzaSyC9N5HdZl15OjRcuOFxZ1SwngjCxIebbYM" />

Дальше создаем необходимый сервис:
MqlReadService readService = FreebaseServices.CreateMqlReadService();

Для поиска по имени сущности нужно отправить следующий MQL запрос, который использует regex:
[{
"type":"/music/artist",
"name":null,
"name~=":"^The Sco*$"
}]

Делается это очень просто с использованием dynamic:
dynamic films = new ExpandoObject();
films.type = "/film/film";
films.name = FreebaseHelpers.Operators.CreateLikeOperator("^The Sco*$");

Теперь собственно делаем запрос и получаем данные. Синхронно
MqlReadServiceResponse result = _readService.Read(films);
или асинхронно
MqlReadServiceResponse result = await _readService.ReadAsync(films);

Под капотом используется новый HttpClient и его асинхронные возможности.

Далее получаем имя сущности
var name = result.Results[0].name;

Results — массив dynamic. Так как ответ зависит от запроса, то есть динамический.

P.S. Существует уже готовый autocomplete, который имеет достаточно привлекательный вид и функционал. Но мне надо было сделать свою логику по кешированию данных в свою базу данных.

С autocomplete разобрались, едем дальше. Далее на странице фильма мне надо вывести описание и картинку. Для этого можно воспользоваться Topic Service, но его структура ответа достаточно сложная — надо разбираться где достать нужную информацию. Для упрощения были созданы TextService и ImageService. Поэтому решил использовать их.
string id = "/en/the_animal";
var textService = FreebaseServices.CreateTextService();
var response = await textService.ReadAsync(id);
string description = response.Result;

Получение ссылки на картинку:
string id = "/en/the_animal";
var imageService = FreebaseServices.CreateImageService();
string image = imageService.GetImageUrl(id, maxwidth: "150");

Если же вам надо сделать несколько запросов асинхронно реализован функционал.
 dynamic thescorpions = new ExpandoObject();
thescorpions.name = "The Scorpions";
thescorpions.type = "/music/artist";

dynamic thepolice = new ExpandoObject();
thepolice.name = "The Police";
thepolice.type = "/music/artist";

List<MqlReadServiceResponse> multiFreebaseResponse = readService.ReadMultipleAsyncWithWait(thescorpions, thepolice);


Если у вас есть идеи как это можно было сделать лучше, буду рад их услышать.
Tags:
Hubs:
+9
Comments9

Articles

Change theme settings