SharEDITor

教你成为全栈工程师(Full Stack Developer) 二十五-为你的网站添加强大的搜索功能

全栈技术 教你成为全栈工程师(Full Stack Developer) 发表于 2016-05-10 16:22:45 阅读1316次


当你的网站文章内容变多时,搜索的需求会逐渐显现,mysql的like功能无论从性能还是效果上都是一个山寨的实现,本节帮你集成elasticSearch实现专业的搜索功能

请尊重原创,转载请注明来源网站www.shareditor.com以及原始链接地址

elasticSearch安装

elasticSearch服务的安装请见我的上一篇文章《教你成为全栈工程师(Full Stack Developer) 二十四-ES(elasticsearch)搜索引擎安装和使用

 

elastic-bundle插件安装

 

需要在我们的symfony2项目中安装elastic-bundle插件,执行

[root@centos7vm mywebsite]# composer require friendsofsymfony/elastica-bundle

 

配置方法

 

修改app/AppKernel.php添加如下注册:

new FOS\ElasticaBundle\FOSElasticaBundle(),

 

并在app/config/config.yml中添加

fos_elastica:
    clients:
        default: { host: localhost, port: 9200 }
    indexes:
        app:
            types:
                blogpost:
                    mappings:
                        title:
                            type: string
                            index: analyzed
                            analyzer: ik_max_word
                        body:
                            type: string
                            index: analyzed
                            analyzer: ik_max_word
                    persistence:
                        driver: orm
                        model: AppBundle\Entity\BlogPost
                        provider: ~
                        listener:
                            insert: true
                            update: true
                            delete: true
                        finder: ~

 

解释一下

 

这里的clients配置的是本地elasticSearch服务的host和port

app是我们应用的名字,你可以随意改成你指定的名字,比如shareditor

blogpost是我们应用里不同数据的名字,每一个都会把索引集中建到一起

title和body是我们要搜索的域,这里我们指定了切词器是ik_max_word

persistence里配置了blogpost的读取orm,也就是BlogPost这个Entity

 

 

 

批量生成索引

执行

[root@centos7vm mywebsite]# php app/console fos:elastica:populate

ps:这一句只在第一次集成elasticSearch的时候执行,以后每当有新文章发布就会自动写入索引,无需手动更新

请尊重原创,转载请注明来源网站www.shareditor.com以及原始链接地址

下面我们开始修改网站添加搜索功能

 

添加action

 

修改src/AppBundle/Controller/BlogController.php,增加如下方法:

    public function searchAction(Request $request)
    {
        $query = $request->get('q');
        $finder = $this->container->get('fos_elastica.finder.app.blogpost');
        $paginator = $this->get('knp_paginator');
        $results = $finder->createPaginatorAdapter($query);
        $pagination = $paginator->paginate($results, 1, 10);

        return $this->render('blog/search.html.twig', array('pagination' => $pagination,
            'query' => $query,
            'latestblogs' => BlogController::getLatestBlogs($this),
            'recommends' => BlogController::getRecommends($this)));
    }

解释一下

$request->get('q');这是从url参数里获取q这个参数来作为query词,后面网页修改里会通过form表单的input空间传递q的value

$this->container->get('fos_elastica.finder.app.blogpost');这是根据config.yml里的配置获取finder实例来做搜索用

下面利用$paginator做翻页,每页10条,默认展示第一页

 

添加路由配置

 

修改app/config/routing.yml,添加

blog_search:
    path:     /blogsearch
    defaults: { _controller: AppBundle:Blog:search }

修改网页模板

 

修改app/Resources/views/base.html.twig,增加如下代码:

    <div class="col-sm-8 col-xs-10"><h1><a href="{{ path('homepage') }}" style="text-decoration: none;color: white;">SharEDITor</a></h1></div>
    <div class="col-sm-3 col-xs-1">
        <form action="{{ path('blog_search') }}" style="margin-top: 10px;">
            <input type="search" name="q" placeholder="搜文章" maxlength="200" style="background-color: transparent;">
        </form>
    </div>

这其实就是在网页顶部增加了一个搜索框,这里面的input输入框的name设置成q,刚好对应了上面的$request->get('q');

 

搜索结果页

 

为了简单,我们尽量复用博客列表页,拷贝app/Resources/views/blog/list.html.twig到app/Resources/views/blog/search.html.twig,把

{% block title %}{{ subject.name }} - SharEDITor - 关注大数据技术{% endblock title %}

改成

{% block title %}{{ query }}的搜索结果 - SharEDITor - 关注大数据技术{% endblock title %}