Интеграция ваших источников данных с федеративным поиском Windows 7

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

Для упрощения поиска информации в Windows Vista был разработан инструмент Windows Search, который позволяет легко и удобно искать информацию на основе заранее подготовленных индексов. В Windows 7 тема поиска нашла свое продолжение и в новой операционной системе появился инструмент Windows 7 Federated Search.

Windows 7 Federated Search – это инструмент, который позволяет искать информацию в сети на основе Windows Explorer. В качестве источника данных в этом случае может выступать все что угодно – корпоративный сайт, интернет-магазин, интернет-аукционы и т.д.

Отличие федеративного поиска от Windows Search заключается в том, что механизмы федеративного поиска не индексируют источники данных, а просто обращаются к ним с просьбой выполнить поисковый запрос. Федеративный поиск ориентирован именно на распределенные удаленные источники информации. Когда речь идет об удаленных источниках, их индексация может быть неэффективной и привести к излишнему расходу трафика. Именно поэтому выбран подход, при котором задача обработки поискового запроса ложится на плечи удаленного источника. Таким образом, появляется возможность подключить все удаленные источники и выполнять поиск по ним не выходя из привычного Windows Explorer.

Несмотря на все удобство такого поиска, реализация провайдера поиска является очень простой задачей. Федеративный поиск в Windows 7 базируется на стандарте OpenSearch 1.1 и работает следующим образом. Для выполнения поиска Windows 7 обращается к внешему веб-сервису, построенному на базе REST-подхода. Это означает, что искомая строка, а также другие данные, необходимые для поиска, передаются в URI при обращении к этому веб-сервису. Веб-сервис на основе этих данных должен выполнить поиск в своем источнике данных и вернуть результат в формате RSS или AtomPub. После этого Windows 7 представит результаты поиска из полученных данных в виде файлов и отобразит их пользователю.

Для добавления своего провайдера поиска в Windows 7 необходимо создать файл описания этого провайдера. Формат этого файла базируется на XML и содержит информацию о данном сервисе поиска, в т.ч. формат URI для обращения к сервису.

Таким образом, для реализации собственного провайдера федеративного поиска в Windows 7 необходимо выполнить два несложных действия – создать REST-сервис для поиска информации и сделать для него файл описания.

Давайте рассмотрим процесс создания провайдера поиска на следующем примере. Имеется список книг с описанием, автором и другой информацией. В данном случае этот список содержится в файле XML (для демонстрационного примера). В качестве источника данных можно использовать все что угодно. Сделаем провайдер поиска по этому списку.

Файл описания провайдера поиска представляет собой XML-файл и имеет расширение .osdx. Этот файл имеет следующую структуру.

<?xml version="1.0" encoding="utf-8" ?>
<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/">
  <ShortName>Federated Search sample provider</ShortName>
  <Url type="application/rss+xml" template="http://somehost.com/search/?q={searchTerms}&amp;start={startIndex}&amp;count={count}" />
</OpenSearchDescription>

В секции Url этого файла задается шаблон адреса, который будет использоваться при обращении к веб-сервису. Видно, что этот адрес может принимать совершенно различный вид. В шаблоне адреса используется несколько секций, в которые будут подставляться значения. Главная секция – это секция searchTerms. В эту секцию будет подставляться строка для поиска. Федеративный поиск Windows 7 получает данные постранично, поэтому существуют секции count и startIndex, которые задают размер и номер страницы. Это необходимо для, того, чтобы Windows смогла получить первые результаты поиска, отобразить их пользователю, а затем заняться остальными элементами.

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

<?xml version="1.0" encoding="utf-8" ?>
<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/">
  <ShortName>Federated Search sample provider</ShortName>
  <Url type="application/rss+xml" template="http://localhost:8731/FederatedSearchProviderSample/search/{searchTerms}/?start={startIndex}&amp;count={count}" />
</OpenSearchDescription>

Последнее, что необходимо сделать – это создать сам сервис, который будет выполнять поиск. В этом случае нет привязки к конкретной технологии и единственное требование – сервис должен возвращать результат в формате RSS/Atom. Понятно, что сам сервис может быть построен на совершенно различных платформах и технологиях. Это может быть PHP, Ruby, Native CGI и т.д. Если рассматривать набор технологий для построения REST-сервисов от Microsoft, то лучший в данном случае выбор – использование возможностей WCF для построения REST-сервисов. Построению подобных сервисов уже уделено немало внимания, поэтому я не буду подробно останавливаться на этом, а опишу лишь ключевые шаги.

Первое, что необходимо сделать — это определить контракт. В контракте будут присутствовать две операции — выполнения поиска и получения детальной информации.

[ServiceContract]
[ServiceKnownType(typeof(Atom10FeedFormatter))]
[ServiceKnownType(typeof(Rss20FeedFormatter))]
public interface ISearchProvider
{
  [OperationContract]
  [WebGet(UriTemplate = "search/{searchTerms}/*")]
  SyndicationFeedFormatter Search(string searchTerms);

  [OperationContract]
  [WebGet(UriTemplate = "details/{id}")]
  Stream Description(string id); 
}

Самое главное, на что нужно обратить внимание в этот момент – определение шаблона URI. Как видно в данном случае шаблон search/{searchTerms}/* полностью соответствует тому, что был определен в файл описания.

Остается только реализовать этот сервис. При реализации необходимо учитывать указанные параметры при обращении к сервису (searchTerms, start, count) и разбивать результат поиска на страницы, если это необходимо. Для этого идеально подходят методы LINQ - Take/Skip. Таким образом, реализация сервиса будет выглядеть следующим образом.

public class SearchProvider : ISearchProvider
{
  public SyndicationFeedFormatter Search(string searchTerms)
  {
    int count;
    int startIndex;

    int.TryParse(WebOperationContext.Current.IncomingRequest.UriTemplateMatch.QueryParameters.Get("count"), out count);
    int.TryParse(WebOperationContext.Current.IncomingRequest.UriTemplateMatch.QueryParameters.Get("start"), out startIndex);

    var result = SearchBooks(searchTerms);

    if (count > 0)
    {
      if (startIndex >= 0)
      {
        result = result.Skip(count * (startIndex - 1)).Take(count);
      }
      else
      {
        result = result.Take(count);
      }
    }

    return new Rss20FeedFormatter(
      new SyndicationFeed("Federated search sample", String.Empty, null,
        from item in result
        select new SyndicationItem(item.Element(XName.Get("name")).Value,
          item.Element(XName.Get("description")).Value,
          new Uri(WebOperationContext.Current.IncomingRequest.UriTemplateMatch.BaseUri.ToString() + @"/details/" + item.Element(XName.Get("id")).Value))
          {
            PublishDate = DateTimeOffset.Parse(item.Element(XName.Get("date")).Value),
          }));
  }

  //...
}

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

После того, как сервис готов и запущен, необходимо открыть файл описания сервиса (.osdx) в Windows и согласиться с предложением добавить провайдер поиска. После этого этот провайдер появится в общем списке провайдеров поиска.

Теперь, когда веб-сервис работает и провайдер поиска успешно добавлен, можно искать на сетевом ресурсе прямо из Windows Explorer. Кроме того, можно воспользоваться окном предварительного просмотра. По умолчанию в него загружается содержимое, которое расположено по адресу, на который ссылается данный пункт (в демонстрационном приложении – это /details/{id}). По этому адресу может быть расположено HTML-содержимое, которое будет отображаться пользователю.

Как видно, реализация провайдера поиска для Windows 7 Federated Search является очень простой, однако, может сделать использование ваших данных намного удобней и проще. Одним из наиболее удачных примеров внедрения федеративного поиска по внешним источникам является провайдер поиска для корпоративных сайтов на базе Sharepoint. Почему бы и нам не реализовать подобную функциональность для своих приложений?