0

I'm developing a Zend Framework 2 application, that should provide:

  • a search in projects with a result list of projects
  • a single project view
  • a search in images with a result list of images (every image belongs to a project)

Also there are two main entities: image and project andthe first idea was to create two modules (Image and Project) and to give to each of them a separate search fuctionaly. But it would mean much of duplicated code. OK, maybe a separate Search module? But then this module would essentially depend on the other modules.

What would be a good approach for such case? Are there a best practice for this?

4

2 回答 2

1

我写了一个 ZF2 弹性搜索模块,但它是闭源的。它使模块能够将可搜索的数据放入 ES。我不能发布代码,但我可以解释它是如何工作的。

中央模块是Search。搜索包含两个主要界面:Search\Repository\ItemRepositoryInterfaceSearch\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 id 并获取类型。通常,每个实体都有自己的类型(因此我可以搜索所有图像和项目,或仅查询图像类型)。

我已经为博客/事件系统实现了这个。将博客文章持久化到数据库中的服务类触发事件,而 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);
    });
}

因为Articleimplements SearchableInterface,所以效果很好。现在我的博客不必处理搜索,搜索也不必处理博客。但是,您想知道,文章是如何转换为搜索文档的?

我有一个类似于 ZF2 水合器的水合器机制。它不会将任何对象转换为数组(反之亦然)。它将SearchableInterface对象转换为 Elastic Search Document(用于存储对象),并将 Elastic Search Result(在搜索查询后返回)SearchableInterface再次转换为对象。

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

每种类型都有自己注册的保湿剂。所有这些不同的水合器都被收集到一个HydratorManager基本上是一个Zend\ServiceManager\AbstractPluginManager. 这个插件管理器被注入到存储库和服务中。

因此,在服务内部,会发生以下情况:

  1. $object->getType()检查
  2. 对于它的类型,获取对应的 hydrator
  3. 水合extract()器被称为$object$document
  4. 底层 ES 客户端用于持久化文档(是添加还是更新,取决于$object->getElasticSearchId()

对于存储库,给定一个查询type:image name:Mountain,会发生以下情况:

  1. search()使用给定查询调用存储库
  2. 该字符串用于 ES 查询对象并被执行
  3. 结果被迭代
  4. 对于每个结果,都会检查类型
  5. 对于它的类型,获取对应的 hydrator
  6. 水合hydrate()器被称为$result$object
  7. 返回对象的集合
于 2014-12-29T10:13:25.800 回答
0

我会创建某种“搜索接口”,每个模块都会实现它来搜索自己的数据。然后您的搜索模块可以检查所有可用模块是否包含此接口,如果包含,则使用它来搜索其数据...

我猜的缺点是搜索代码是在每个模块中实现的......

于 2014-12-28T13:03:08.310 回答