Реализация полнотекстового поиска с SoftInform Search SDK

Мы с вами уже достаточно подробно говорили о работе с SoftInform Search SDK - программным продуктом, который позволит достаточно быстро и просто встроить средства полнотекстового поиска в создаваемое Windows-приложение. Сегодня продолжим знакомство с этим программным продуктом.

В прошлый раз мы успешно освоили как простой поиск по запросам, так и более сложный вариант поиска, включающий в себя обработку составного запроса, который включает в себя только те результаты поиска, в которых одновременно встречаются два подзапроса. Напомню, что для отсылки запроса сервера мы с вами должны сначала к нему подключиться, а затем нам помогут экземпляры классов, реализующих интерфейсы ISITextSearchRequestEx (для формирования поискового запроса и отправки его к серверу) и ISIDocumentsList (для обработки полученного от сервера списка документов).

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


Составные запросы (продолжение)

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

 

Мы с вами рассмотрим код тоже достаточно подробно, а о том, какие типы используются в них, вам помогут вспомнить листинги, размещенные в предыдущей части нашего разговора о SoftInform Search SDK. В листинге 1 вы можете увидеть код для работы с составным запросом, реализующим булевскую операцию "или". После того, как вы ознакомитесь с листингом, мы его разберем.

Листинг 1

i := Pos('[OR]', s);
if i > 0 then
begin
 query1 := Copy(s, 1, i - 1);
 query2 := Copy(s, i + 4, MaxInt);
 ABinaryRequest := AGenerator.CreateUnionSearchRequest;
 ATextRequest := AGenerator.CreateTextSearchRequest;
 ATextRequest.Query := query1;
 ATextRequest.WordOption := siwoExact;
 ABinaryRequest.SubRequestA := ATextRequest;
 ATextRequest := AGenerator.CreateTextSearchRequest;
 ATextRequest.Query := query2;
 ATextRequest.WordOption := siwoExact;
 ABinaryRequest.SubRequestB := ATextRequest;
 ARequest := ABinaryRequest;
end;

Итак, что же в этом листинге, собственно говоря, написано? Сначала, как вы наверняка поняли, мы обрабатываем запрос - то есть выделяем его составные части и удостоверяемся, что это действительно запрос, реализующий логическое "или". Хочу напомнить, что особенность SoftInform Search SDK заключается в том, что программист сам обрабатывает синтаксис формальных составных запросов, что, конечно, несколько увеличивает программный код, однако если действовать не так, как в приведенном примере, а выносить предварительную обработку запросов в отдельный метод, то это не будет ухудшать читабельность и внутреннюю логику программного кода. При этом такой подход обеспечивает возможность гибкого изменения синтаксиса, что может быть полезно, например, в случае необходимости локализации приложения на другой язык.

Впрочем, это все, можно сказать, лирика. Как видите, после обработки запроса и разбиения его на подзапросы мы используем метод CreateUnionSearchRequest, который как раз и реализует логическое "или". Собственно говоря, именно в этом и заключается ключевое отличие данного листинга от того, который был рассмотрен нами в прошлой части статьи о SoftInform Search SDK.


Информация о найденных документах

Поскольку достаточно часто нужно будет отображать не просто количество найденных документов и перечисление их названий, но и какую-никакую информацию об этих документах, то будет уместным поговорить немного и о том, каким именно образом можно извлечь подобную информацию, используя стандартные API SoftInform Search SDK. Для этого обратимся к листингу 2, в котором приведен код функции, показывающей информацию о размере каждого из удовлетворяющих поисковому запросу документов.

Листинг 2

function GetDocSize(DocID: ISIDocumentID): Integer;
var
 ASysAttrs: ISIDocumentAttributes;
 i: Integer;
begin
 Result := -1;
 ASysAttrs := DocID.SystemAttributes;
 for i := 0 to ASysAttrs.Count - 1 do
 begin
  if ASysAttrs.AttributeName[i] = '$size' then
  begin
   Result := ASysAttrs.AttributeValue[i];
   Break;
  end;
 end;
end;

Итак, давайте разбираться с тем, что написано в листинге 2. На самом деле, думаю, достаточно много понятно из самого программного кода, но дополнительные пояснения, конечно же, не будут лишними.

Документ, который мы будем "исследовать", передается в нашу функцию с помощью аргумента, имеющего класс, реализующий интерфейс ISIDocumentID. Из экземпляров данных классов состоит список выходных документов, выдаваемый "наружу" поисковым сервером SoftInform Search SDK после успешного выполнения поискового запроса. Для получения информации о найденном документе мы используем интерфейс ISIDocumentAttributes. Этот интерфейс реализует класс, который используется в свойстве SystemAttributes нашего аргумента функции. У этого класса есть свойства Count (количество атрибутов), AttributeType (массив, описывающий типы атрибутов), AttributeName (аналогичный ему массив, только с именами этих атрибутов) и AttributeValue (здесь уже, как несложно догадаться, записаны значения атрибутов). В данном случае из всех атрибутов документов выбираем только их размер, но, сами понимаете, в реальных приложениях дело только им ограничиваться не будет.


Работа с поисковыми индексами

Что ж, по большому счету, мы завершили рассмотрение всего, что связано с выполнением поисковых запросов. Потому что практически все остальное, что их непосредственно касается, можно в той или иной степени свести к тому, что уже было сказано о них выше. Да и газетная статья или даже цикл таких статей - это все-таки не руководство разработчика, использующего SoftInform Search SDK, а потому рассмотреть абсолютно все аспекты и все приемы, которые могут пригодиться разработчику, использующему в создаваемых им приложениях данный программный продукт, нет совершенно никакой возможности. Так что мы перейдем к следующему важному, если можно так сказать, разделу - к работе с поисковыми индексами, которые являются краеугольными камнями всего полнотекстового поиска, в том числе и поиска с помощью SoftInform Search SDK.

Рассказывать долго о том, что такое поисковые индексы и как они работают, я сейчас не буду - не так давно я уже поднимал эту тему на страницах "Компьютерных вестей" в статье "Поиск глазами программиста". Так что если вам интересно внутреннее устройство поисковых индексов, то рекомендую обратиться к ней.

Разговор об индексах мы начнем с создания нового поискового индекса. Процесс этого самого создания от начала до конца можно увидеть в листинге 3.

Листинг 3

procedure CreateIndex;
var
 SiIndex: ISIIndex;
 SiLocalServer: ISILocalServer;
begin
// Здесь должен быть код подключения к серверу
// ...
// Создаём индекс SearchInformIndexExamlpe.siidx
// в той же папке, где находится само приложение
 SiIndex := SiLocalServer.CreateIndex
 (IncludeTrailingPathDelimiter(ExtractFilePath(ParamStr(0)))
 + 'SearchInformIndexExamlpe.siidx');
// Проверяем, создалось что-нибудь, или нет
 if SiIndex = nil then
 begin
  ShowMessage('Индекс создать не удалось.');
 end
 else
 begin
// Если всё-таки что-нибудь создалось,
// осуществляем начальную настройку. Handle -
// дескриптор приложения, нужен для уникальности
// конфигурации каждого клиента
  SiIndex.ClearIndexData;
  SiIndex.Configurate(Handle, 0);
 end;
end;

Как видите, код подключения к серверу в этом листинге для простоты восприятия и сокращения объема программного кода опущен, вы можете найти его в первой статье, посвященной SoftInform Search SDK. Самый главный интерфейс, который поможет нам при работе с индексами, - это ISIIndex. Для создания нового индекса, как нетрудно догадаться, используем метод с говорящим названием CreateIndex. В качестве аргумента этому индексу передается полный путь к нему на диске. Если индекс по каким-либо причинам создать не удается, выводим пользователю сообщение об этом, а если удается, то очищаем его и проводим начальную конфигурацию.

Что ж, на сегодня, пожалуй, о SoftInform Search SDK достаточно, и, хотя разговор об этом замечательном и чрезвычайно интересном программном продукте мы еще не закончили, но естественные ограничения по объему газетной статьи не позволяют завершить разговор о SoftInform Search SDK прямо сейчас, и нам с вами еще есть что обсудить относительно работы с поисковыми индексами.

Вадим СТАНКЕВИЧ,
dreamdrusch@tut.by

Версия для печатиВерсия для печати

Номер: 

24 за 2010 год

Рубрика: 

Software
Заметили ошибку? Выделите ее мышкой и нажмите Ctrl+Enter!