Как структурировать / модулировать приложение с помощью кросс-модульного поиска?

Я разрабатываю приложение Zend Framework 2, которое должно обеспечить:

  • поиск в проектах с результирующим списком проектов
  • один вид проекта
  • поиск изображений с результирующим списком изображений (каждое изображение принадлежит проекту)

Также есть две основные сущности: image а также project и первой идеей было создать два модуля (Image а также Project) и дать каждому из них отдельный поиск по желанию. Но это будет значить много дублированного кода. Хорошо, может быть отдельный Search модуль? Но тогда этот модуль будет существенно зависеть от других модулей.

Что было бы хорошим подходом для такого случая? Есть ли лучшая практика для этого?

0

Решение

Я написал модуль упругого поиска ZF2, но это закрытый источник. Это позволяет модулям помещать доступные для поиска данные в ES. Я не могу опубликовать код, но я могу объяснить, как он работает.

Центральный модуль Search, Поиск содержит два основных интерфейса: Search\Repository\ItemRepositoryInterface а также Search\Service\ItemServiceInterface, Хранилище для поиска предметов, сервис для хранения / удаления предметов.

interface ItemRepositoryInterface
{
public function search($query, $limit = 10);
}

interface ItemServiceInterface
{
public function insert(SearchableInterface $object);
public function remove(SearchableInterface $object);
}

SearchableInterface это интерфейс, который мои модели / сущности могут использовать для «поиска». Это позволит ES установить идентификатор ES и захватить тип. Обычно каждый объект получает свой собственный тип (поэтому я могу искать все изображения и проекты или запрашивать только типы изображений).

Я реализовал это для системы блогов / событий. Класс обслуживания, который сохраняет статью блога в базе данных, вызывает события, и ElasticSearch является одним из слушателей:

public function onBootstrap(MvcEvent $e)
{
$app = $e->getApplication();
$sm  = $app->getServiceManager();
$em  = $app->getSharedManager();

$em->attach('Blog\Service\ArticleService', 'create', function($e) use ($sm) {
$searchService = $sm->get('Search\Service\ItemService');
$article       = $e->getArticle();

$searchService->insert($article);
});
}

Так как Article инвентарь SearchableInterfaceэто прекрасно работает. Теперь мой блог не должен иметь дело с поиском, а поиск не должен иметь дело с блогом. Интересно, а как статья преобразуется в поисковый документ?

У меня есть гидраторный механизм, который работает как гидратор ZF2. Он не конвертирует какой-либо объект в массив (и наоборот). Это превращает SearchableInterface объект в упругом поиске Document (для хранения объекта) и он преобразует упругий поиск Result (который возвращается после поискового запроса) в SearchableInterface объект снова

interface HydratorInterface
{
public function extract(SearchableInterface $object);
public function hydrate(Result $object);
}

Каждый тип имеет свой собственный зарегистрированный гидратор. Все эти разные гидраторы собраны в HydratorManager который в основном Zend\ServiceManager\AbstractPluginManager, Этот менеджер плагинов внедряется в хранилище и сервис.

Итак, внутри сервиса происходит следующее:

  1. $object->getType() проверено
  2. Для его типа выбран соответствующий гидратор
  3. Гидратор extract() призван повернуть $object в $document
  4. Базовый клиент ES используется для сохранения документа (либо он добавлен, либо обновлен, в зависимости от результата $object->getElasticSearchId()

Для хранилища дан запрос type:image name:Mountainпроисходит следующее:

  1. Хранилище search() вызывается по заданному запросу
  2. Строка используется для объекта запроса ES и выполняется
  3. Результаты повторяются
  4. Для каждого результата проверяется тип
  5. Для его типа выбран соответствующий гидратор
  6. Гидратор hydrate() призван повернуть $result в $object
  7. Коллекция объектов возвращается
1

Другие решения

Я хотел бы создать своего рода «интерфейс поиска», который каждый модуль будет реализовывать для поиска своих данных. Тогда ваш поисковый модуль может проверить все доступные модули, если они содержат этот интерфейс, и если они есть, использовать его для поиска своих данных …

Недостаток, я думаю, в том, что код поиска реализован в каждом модуле …

0