Мы с вами уже достаточно подробно говорили о работе с 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
Горячие темы