如何使用跨模块搜索来构建/模块化应用程序?

时间:2014-12-27 23:57:40

标签: php architecture zend-framework2 structure modularization

我正在开发一个Zend Framework 2应用程序,应该提供:

  • 使用项目结果列表搜索项目
  • 单个项目视图
  • 使用结果图像列表搜索图像(每个图像属于项目)

还有两个主要实体:imageproject,第一个想法是创建两个模块(ImageProject)并为每个模块提供一个单独搜索fuctionaly。但这意味着大量的重复代码。好吧,也许是一个单独的Search模块?但是这个模块基本上取决于其他模块。

这种情况的好方法是什么?对此有最好的做法吗?

2 个答案:

答案 0 :(得分: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是我的模型/实体可以使用的界面" make"它可以搜索。它让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);
    });
}

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

我有一个与ZF2保湿剂一样的保湿机制。它不会将任何对象转换为数组(反之亦然)。它将SearchableInterface对象转换为弹性搜索Document(用于存储对象),并将弹性搜索Result(在搜索查询后返回)转换为{{1}再次反对。

SearchableInterface

每种类型都有自己的保湿剂注册。将所有这些不同的水合物收集到interface HydratorInterface { public function extract(SearchableInterface $object); public function hydrate(Result $object); } 中,基本上是HydratorManager。这个插件管理器被注入到存储库和服务中。

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

  1. 检查Zend\ServiceManager\AbstractPluginManager
  2. 对于它的类型,提取相应的水合物
  3. 调用保姆$object->getType()extract()变为$object
  4. 底层ES客户端用于保留文档(根据$document
  5. 的结果添加或更新文档

    对于存储库,给定查询$object->getElasticSearchId(),会发生以下情况:

    1. 使用给定查询
    2. 调用存储库的type:image name:Mountain
    3. 该字符串用于ES查询对象并执行
    4. 重复结果
    5. 对于每个结果,都会检查类型
    6. 对于它的类型,提取相应的水合物
    7. 调用保姆search()hydrate()变为$result
    8. 返回对象集合

答案 1 :(得分:0)

我会创建某种“搜索界面”,每个模块都会实现搜索自己的数据。然后你的搜索模块可以检查所有可用的模块,如果它们包含这个界面,如果有的话,用它来搜索他们的数据......

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