demontpx/rigid-search-bundle

Symfony 的刚性搜索包

安装: 387

依赖: 0

建议者: 0

安全: 0

星标: 1

关注者: 2

分支: 0

开放问题: 0

类型:symfony-bundle

0.7.4 2021-01-06 17:51 UTC

README

提供了一种使实体可搜索的方法。

搜索结果将按相关性排序,相关性通过计算您可配置的索引字段的权重来得出。

安装

使用 composer 需要此包

composer require demontpx/rigid-search-bundle

用法:使实体可搜索

假设我们想索引一个 NewsItem 实体

class NewsItem {
    public function getId() { return $this->id; }
    public function getTitle() { return $this->title; }
    // ...
}

第一步是创建一个新类,该类实现了 SearchDocumentExtractorInterface 接口。在这里,您定义需要搜索的字段以及它们之间的相对重要性。

class NewsItemDocumentExtractor implements SearchDocumentExtractorInterface {
    public function extractDocument($item): Document {
        // $item should be of the type NewsItem
        
        // The title, description and URL you put in here are only used for display and link to the item
        // They are not searchable unless you add them as fields as well (see below!)
        $document = new Document(
            $item->getTitle(),
            $item->getDescription(),
            $item->getPublishDate(),
            $this->generateUrl($item)
        );
        
        // These are the fields on which items can be found
        // The last argument are the weight values, which can be any relative number 
        $document->addField(new Field('title', $item->getTitle(), 1.0);
        $document->addField(new Field('text', $item->getText(), 0.8);
        $document->addField(new Field('category', $item->getCategoryName(), 0.2);
        $document->addField(new Field('tags', implode(' ', $item->getTagList()->toArray()), 0.25);
        
        return $document;
    }
    
    public function extractId($item): int {
        return $item->getId();
    }
}

第二步是创建另一个新类,该类实现了 ItemSearchManagerInterface

class NewsItemSearchManager implements ItemSearchManagerInterface {
    public function getClass(): string {
        // Classname of the entity
        return NewsItem::class;
    }

    public function getType(): string {
        // Short arbitrary unique name to describe the entity
        return 'news';
    }

    public function getDocumentExtractor(): SearchDocumentExtractorInterface {
        // Return the class created earlier
        // You could, of course, also inject the extractor into this class using the service container and pass it here
        return new NewsItemDocumentExtractor();
    }

    public function fetchAll(): array {
        // This method should return all searchable items of this type (ie: only published news items)
        // This is used when reindexing all items of this type
        // You should figure out for yourself where these entities should come from
        // For example: get these from an EntityRepository
        return $this->repository->fetchAllPublished();
    }
}

将此类注册为容器中的服务

MyBundle\NewsItemSearchManager:
    tags: [demontpx_rigid_search.item_search_manager]

如果一切配置正确,您应该可以使用此命令索引所有 news 项目

bin/console demontpx:search:reindex:type news

下一步是触发索引,当新闻条目被创建、更新或删除时手动删除。这可以通过事件实现,或者您可以在控制器中手动索引和从搜索索引中删除项目

class NewsItemController extends Controller {
    public function newAction() {
        $item = new NewsItem();
        // ... Do your persist logic here
        
        $searchManager = $this->get('demontpx_rigid_search.search_manager');
        $searchManager->index($item);
    }
    
    public function editAction(NewsItem $item) {
        // ... Do your persist logic here
        
        $searchManager = $this->get('demontpx_rigid_search.search_manager');
        $searchManager->index($item);
    }
    
    public function removeAction(NewsItem $item) {
        $oldId = $item->getId();
        
        // ... Do your remove logic here
        
        $searchManager = $this->get('demontpx_rigid_search.search_manager');
        $searchManager->remove($item);
        
        // Doctrine ORM resets the item id to null after a delete, so you might want to use this:
        $searchManager->removeByClassAndId(get_class($item), $oldId);
    }
}

用法:添加搜索字段并显示结果

第一步是将此添加到您的 routing.yaml

demontpx_rigid_search:
    resource: "@DemontpxRigidSearchBundle/Resources/config/routing.yml"
    prefix:   /search

之后,您可以将此添加到任何 Twig 模板中

{{ render(controller('Demontpx\\RigidSearchBundle\\Controller\\SearchController::searchForm', {}, { query: app.request.query.get('query', '') })) }}

这将添加搜索输入字段。提交后,将显示搜索结果。

默认情况下,搜索结果页面将扩展 ::base.html.twig 模板。通过创建 app/Resources/DemontpxRigidSearchBundle/views/Search/searchResult.html.twig 来覆盖整个模板。