Yii2集成Elasticsearch(二)

6 篇文章 0 订阅

背景知识:

  1. 全文搜索可以简单地分为两类,一种是顺序扫描,即我们常见的使用 like %keyword% 方式,扫描整张数据表,在每一条记录中查找;另一种就是索引扫描。elasticsearch就是后者。
  2. 索引扫描分为两部分:创建索引和搜索索引。创建索引的主要步骤是:对原数据进行分词处理(去掉标点和一些无意义的词等等),将得到的词元交给语言处理组件(例如将复数变为单数,将过去式变为一般式等等),最后再将词元交给索引组件建立索引。搜索索引的主要步骤:对用户输入的内容进行分词语言等处理之后,根据词元搜索索引,找到对应的文档id,再根据文档id获得结果。
  3. logstash可以理解为是一个管道,数据从输入端传输到输出端,当然你还可以在管道中防止一些滤网来过滤数据,感兴趣的读者可以详细了解一下。
  4. 在使用ES的时候,注意版本,因为版本和版本之间的差距还是很大的
  5. 在操作ES的时候可以考虑使用官方的可视化工具kibana,或者使用postman,curl命令,当然也可以使用elasticsearch-head,github主页
  6. 本文基于苹果系统做介绍。

在上一篇文章中介绍了ES的安装以及基础知识,还扩展了如何使用logstash将mysql的数据导入到ES中。本文将介绍Yii2框架中如何使用ES。

1.第一步安装扩展:

#局部安装
php composer.phar require --prefer-dist yiisoft/yii2-elasticsearch:"~2.0.0"


#全局安装
composer require --prefer-dist yiisoft/yii2-elasticsearch:"~2.0.0"


2.在web应用的配置文件web.php增加如下的配置:

return [
    //....
    'components' => [
        'elasticsearch' => [
            'class' => 'yii\elasticsearch\Connection',
            'nodes' => [
                ['http_address' => '127.0.0.1:9200'],
                // configure more hosts if you have a cluster
            ],
        ],
    ]
];

3.创建一个搜索类,基于es组件提供的ActiveRecord:

<?php

namespace app\services;
use yii\elasticsearch\ActiveRecord;

class SearchGoods extends ActiveRecord{

    #定义从es中返回结果的字段
    public function attributes()
    {
        return ['goods_id','name','descr','is_sale','price','sale_price','picture'];
    }

    
    #定义索引
    public static function  index(){
        return 'yii';
    }

    
    #定义文档类型
    public static function type(){
        return 'doc';
    }
}

4.在介绍如何使用上述定义的SearchGoods来进行搜索之前,先来讲一下原生基于API的方式:基于上一篇文章的例子,如果要查找yii索引下goods类型中name含有“你好”的的文档:

POST http://localhost:9200/yii/goods/_search
{
    "query":{
        "match":{
            "name":"你好"
            }
        }
}

那么如果我要查看name或者descr中包含“你好”的文档呢?

POST http://localhost:9200/yii/goods/_search
{
    "query":{
        "multi_match":{
            "query":"你好",
            "fields":["name","descr"]
        }
    }
}

由于我们在上一篇文档中给ES配置了IK分词,因此我们可以使用IK提供的高亮显示的功能,例如还是上面的例子,但是要求“你好”这个关键字高亮显示:
 

POST http://localhost:9200/yii/goods/_search
{
    "query":{
        "multi_match":{
            "query":"你好",
            "fields":["title","descr"]
        }
    },
    "highlight" : {
        #左标签
        "pre_tags" : ["<i>"], 
        #右标签 
        "post_tags" : ["</i>"],  
        #高亮的字段
        "fields" : {   
            "descr" : {},
            "name":{}
        }
    }
}
#上面的配置的意思就是:例如有一个文档的内容是{"name":"你好,星期天","descr":"今天天气真好呀"}
#当你搜索"你好"时,这个文档就会被搜索出来,并且结果会有一个highlight属性,值为:
#{"name":"<i>你好</i>,星期天"}
#基于上面的配置,如果想要“你好”在搜索结果中以红色显示,那么只要在搜索结果页中加上如下的css样式即可:
<style>
    i{
        color:red;
    }
</style>

以上就是原生API的查询方法,基于这个原理,我们再来看看使用SearchGoods这个类如何做查询:

<?php


namespace app\controllers;
use app\modules\admin\models\Goods;
use app\services\SearchGoods;
class GoodsController extends BaseController{
    
    #商品控制器中新增基于es搜索的方法
    public function actionSearch(){
        $hightlight=[

            #左标签,配合前端.highlight这个类来实现高亮
            "pre_tags"=>['<span class="highlight">'],
            "post_tags"=>['</span>'],

            #在原生api中写的是{}表示空对象,因此使用php的stdClass来表示空对象
            "fields"=>[
                "name"=>new \stdClass(),
                'descr'=>new \stdClass()
            ]
        ];
        $key=\Yii::$app->request->get('keyword');
        $res=SearchGoods::find()->query([
            'multi_match'=>[
                'query'=>$key,
                "fields"=>['name','descr']
            ]
        ])->highlight($hightlight)->all();
        return $this->render('search',compact('res'));
    }
}

#注意:你完全可以拿SearchGoods这个类当作平常的活动记录类使用,因为yii\elasticsearch\ActiveRecord这个类也继承了 yii\db\BaseActiveRecord;

5.以上就是Yii2集成ES的过程,需要注意的点:

  1. 可以将部分字段信息存入到ES中,然后根据ES返回的搜索结果回溯数据表获取更多的信息,这种方式效率低但是节省空间。第二种方式就是将需要的所有字段信息全部存入到ES中,这种方式就不用回溯数据表了效率高但是空间消耗大
  2. logstash从mysql增量向ES中导入数据时,如果mysql中数据更新或者新增了都是会同步的,但是如果删除了logstash并不会在ES中删除相应的数据。解决方案可以尝试在数据删除后手动向ES发送相应的删除api请求进行删除。
  3. 可以在logstash的mysql配置文件中配置schedule项来实现自动增量

最后欢迎大家关注我的公众号:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值