Как стать автором
Обновить
0

Настройка обработки документов на FAST

Время на прочтение4 мин
Количество просмотров2.3K
Одна из задач при интеграции сторонней поисковой машины в систему — это настройка процесса обработки исходных документов (грубо говоря, индексирования). Сложность настройки такого процесса зависит от функциональных требований к системе поиска и возможностей поисковой машины. Настройка может как ограничиться парой кликов в админке поисковой машины, так и вылиться в написание собственных процедур, скриптов и т.д. Если стандартным возможностям системы (тем более если ее код не может быть модифицирован) мы привыкли доверять, то для собственных скриптов хотелось бы иметь тесты, реализация которых не всегда предусмотрена движком.

Мы столкнулись с необходимостью реализации поиска на платформе MS FAST ESP 5.3. Этот серьезный движок имеет внушительные возможности кастомизации обработки документов, некоторые из которых мы затронули в своем проекте. В-общем-то, мы хотим поделиться нашим способом тестирования кастомных стейджей на этом движке.

Документация достаточно хорошо описывает процесс создания стейджей. Мы не будем ее пересказывать, ограничимся лишь сведениями, необходимыми для понимания изложенного.
В терминологии FAST ESP вся последовательность действий, которая должна быть выполнена при индексировании одного документа, называется Pipeline, а отдельные действия — Stage. Stage запускается в определенном контексте, с которым может взаимодействовать, одним из элементов которого является документ. К примеру, stage может считывать и записывать атрибуты обрабатываемого документа. Схематично весь процесс обработки документов выглядит так:



Стейдж представлен в виде двух файлов — xml-спецификации и реализации (в FAST ESP 5.3 реализация предусматривает использование языка python v.2.3).

Ниже пример стейджа, который записывает в поле quality значение 500, если атрибут документа hotornew имеет значение true.
<processors>
 <processor>
  <load module="processors.SetOnEqual" class="SetOnEqual"/>
  <desc>Set high rank to documents, which have HotOrNew = yes
  </desc>
  <config>
        <param name="Input" value="hotornew" type="str" />
        <param name="Output" value="quality" type="str" />
        <param name="InputFieldValue" value="true" type="str" />
        <param name="OutputFieldValue" value="500" type="int" />
        
  </config>
  <ops>
    <add/>
  </ops>
 </processor>
</processors>

(спецификация непосредственно в тестах не участвует, приведена для целостности картинки)

from docproc import Processor, DocumentException,  ProcessorStatus


class SetOnEqual(Processor.Processor): 

    def ConfigurationChanged(self, attributes): 
        self.input = self.GetParameter('Input') 
        self.output = self.GetParameter('Output') 
        self.inputfieldvalue = self.GetParameter('InputFieldValue')
        self.outputfieldvalue = self.GetParameter('OutputFieldValue')  
   
    def Process(self, docid, document): 
        testField = str(document.GetValue(self.input, None))
        if testField == str(self.inputfieldvalue):
            output = int(self.outputfieldvalue)
            document.Set(self.output,output)
        else:
                document.Set(self.output, 0)
       
        return ProcessorStatus.OK

Для того, чтобы проверить работу созданного стейджа в родном контексте обработки документа, необходимо проделать последовательность действий, указанную в документации:
1. Выложить в определенные каталоги файлы спецификации и реализации;
2. Перезапустить службу обработки документов — Document Processor (procserver. при запуске он компилирует код стейджей);
3. Включить новый стейдж в pipeline;
4. Проиндексировать тестовый документ;
5. Посмотреть на результат обработки документа (можно вывести в лог-файл, а можно “найти” новый документ через стандартный фронтенд и посмотреть все атрибуты документа).

В случае, если мы не получили ожидаемого результата (к примеру в документе выставили поле hotornew = true, a значение поля Quality так и не изменилось), нам придется заняться отладкой, что означает:
— Поискать ошибку в логе procserver’a;
— Проконтролировать, сделал ли конкретно наш стейдж то, что от него просили, поставив стейджи Spy до и после выполнения тестируемого стейджа. (Spy выгружает дамп документа вместе с его атрибутами в файл на диске);
— Поискать ошибку в коде стейджа.

После того как ошибка поправлена, нужно опять проверить — т.е. опять выполнить шаги 1, 2, 4, 5.
Это муторно. Удобнее отлаживать код стейджа “как есть” привычными методами, например в unit-тесте:



Поэтому для “воссоздания” контекста мы сделали примитивные моки классов, с объектами которых работает стейдж:

class Document(object):
    """
    Mock сущности Document
    """
    
    def GetValue(self, name, default):
        return getattr(self, name, default)
    
    def Set(self, field, value):
        setattr(self, field, str(value))


class Processor (object):
    """
    Mock сущности Processor
    """

    def GetParameter(self, name):
        return getattr(self, name)

    def Set(self, field, value):
        setattr(self, field, str(value))

В реальности сущность document предоставляет и другие методы. Мы ограничились теми, что используем.
Теперь можно писать/отлаживать/тестировать стейдж без поискового движка:

import unittest
import docproc.Processor as proclib
from docproc import ProcessorStatus
import SetOnEqual

class testSetOnEqual(unittest.TestCase):
   
    def setUp(self):
        self.stage = SetOnEqual.SetOnEqual()
        self.stage.Set('Input', 'hot')
        self.stage.Set('Output', 'quality')
        self.assertEquals(self.stage.GetParameter('Input'), 'hot')
        self.assertEquals(self.stage.GetParameter('Output'), 'quality')
      
    def test_true(self):
        self.stage.Set('InputFieldValue', 'true')
        self.stage.Set('OutputFieldValue', '600')
        doc = proclib.Document()
        doc.Set('hot', 'true')        

        self.stage.ConfigurationChanged('')
        status = self.stage.Process("docid", doc)
        self.assertEquals(status, ProcessorStatus.OK)
        self.assertEquals(doc.GetValue('quality', ""), '600')
        
    def test_false(self):
        self.stage.Set('InputFieldValue', 'true')
        self.stage.Set('OutputFieldValue', '600')
        doc = proclib.Document()
        doc.Set('hot', 'no')        

        self.stage.ConfigurationChanged('')
        status = self.stage.Process("docid", doc)
        self.assertEquals(status, ProcessorStatus.OK)
        self.assertEquals(doc.GetValue('quality', ""), '0')
        
        
def suite():

    suite = unittest.TestSuite()
    suite.addTest(unittest.makeSuite(testSetOnEqual))
    return suite

    
if __name__ == "__main__":
   unittest.main()

Код целиком есть в архиве.

Что нам дал такой подход:
— Упрощение жизни себе (здорово экономит время и позволяет не отходить от практики модульного тестирования);
— Упрощение жизни тестировщику.

Автор:
Лия Шабакаева
Ведущий разработчик
Департамент разработки Softline
Теги:
Хабы:
+4
Комментарии3

Публикации

Информация

Сайт
www.softline.ru
Дата регистрации
Дата основания
1993
Численность
1 001–5 000 человек
Местоположение
Россия
Представитель
Softliner

Истории