Laravel中使用ElasticSearch

1,995 阅读2分钟

前言

Elasticsearch 是一个基于 Apache Lucene (TM) 的开源搜索引擎,无论在开源还是专有领域,Lucene 可 以被认为是迄今为止最先进、性能最好的、功能最全的搜索引擎库。

Elasticsearch 也是使用 Java 编写并使用 Lucene 来建立索引并实现搜索功能,但是它的目的是通过简单连贯的 RESTful API 让全文搜索变得简单并隐藏 Lucene 的复杂性。

这里不在讲解es的基础,下面直接与laravel进行融合使用,走着!!

安装类库包文件

使用composer安装elasticsearch类库包

composer require elasticsearch/elasticsearch -vvv

创建index索引(mysql中的数据表)

这里推荐用 Laravel 自带的 Artisan 命令行功能。

php artisan make:command ESOpenCommand

会在 app\Console\Commands\ 目录下创建 ESOpenCommand.php

    /**
     * The name and signature of the console command.
     * 这是命令的名字
     * @var string
     */
    //运行命令的名称
    protected $signature = 'command:esInit';
    
    /**
     * The console command description.
     * 命令的描述
     * @var string
     */
    protected $description = 'Command description';

    /**
     * Create a new command instance.
     * @return void
     */
    public function __construct()
    {
        parent::__construct();
    }

    /**
     * 在这里写要写的东西
     * Execute the console command.
     * @return mixed
     */
    public function handle()
    {
        //coding,待会儿我们要在这里写代码
    }

在 ESOpenCommand.php 里的 handle () 方法里写

//主机地址 如:[127.0.0.1:9200]
$config = config('elasticSearch.host');
//要生成的索引 如:test
$index = config('elasticSearch.index');
// 得到es客户端对象
$client = ClientBuilder::create()->setHosts($config)->build();

//检查要创建的index类型是否存在,存在删除
if ($client->indices()->exists(['index' => $index])) {
    $this->warn("Index {$index} exists, deleting...");
    $client->indices()->delete(['index' => $index]);
}

$this->info("Creating index: {$index}");

// 创建索引
$params = [
    // 生成索引的名称
    'index' => $index,
    // 类型 body
    'body' => [
        'settings' => [
            // 分区数
            'number_of_shards' => 5,
            // 副本数
            'number_of_replicas' => 1
        ],
        'mappings' => [
            '_doc' => [
                '_source' => [
                    'enabled' => true
                ],
                // 字段  类似表字段,设置类型
                'properties' => [
                    'fang_name' => [
                        // 相当于数据查询是的 = 张三你好,必须找到张三你好
                        'type' => 'keyword'
                    ],
                    'fang_desn' => [
                        'type' => 'text',
                        //中文分词  张三你好   张三  你好 张三你好
                        'analyzer' => 'ik_max_word',
                        'search_analyzer' => 'ik_max_word'
                    ]
                ]
            ]
        ]
    ]
];

return $client->indices()->create($params);

执行运行命令

 php artisan command:esInit

效果图如下:

image.png

打开kibana检查test是否创建成功

//查看索引状态
GET /_cat/indices

image.png

单例封装es类库

<?php

namespace App\Business;


use Elasticsearch\ClientBuilder;

class ElasticSearchBusiness
{

    /**
     * 定义单例es
     * @var \Elasticsearch\Client
     */
    private $Esclient;

    /**
     * 定义单例变量
     * @var
     */
    private static $_instance;

    /**
     * 私有构造方法
     */
    private function __construct()
    {
        $hosts = config('elasticSearch.host');

        $this->Esclient = ClientBuilder::create()->setHosts($hosts)->build();
    }

    /**
     * 入口文件
     * @return ElasticSearchBusiness
     */
    public static function getInstance()
    {
        if (self::$_instance == false) {
            self::$_instance = new self();
        }

        return self::$_instance;
    }

    /**
     * 同步es文档 (新增/修改)
     * @param $params
     * @return array|callable
     */
    public function syncFangEsInfo($params)
    {
        return $this->Esclient->index($params);
    }

    /**
     * 搜索es文档信息 (搜索数据)
     * @param $params
     * @return array|callable
     */
    public function getEsFangData($params)
    {
        return $this->Esclient->search($params);
    }
}

使用单例模式实现es数据更新(新增/修改)

$params = [
    'index' => 'fang',
    'type' => '_doc',
    //id不存在,为新增;存在则修改
    'id' => $result->id,
    'body' => [
         //字段根据自己业务来做...
        'fang_name' => $result->fang_name,
        'fang_desn' => $result->fang_desn,
        'fang_xiaoqu' => $result->fang_xiaoqu,
        'fang_owner_name' => $fangOwner->name,
        'fang_addr' => $result->fang_addr,
        'fang_using_area' => $result->fang_using_area,
        'fang_year' => $result->fang_year,
        'fang_rent' => $result->fang_rent,
        'fang_status' => $result->fang_status == 0 ? '未出租' : '已出租',
        'created_at' => $result->created_at,
    ],
];
// 添加数据到索引文档中
ElasticSearchBusiness::getInstance()->syncFangEsInfo($params);

使用单例模式实现es数据搜索(高亮加分页)

// 拼写es搜索样式
$params = [
    'index' => 'fang',//数据库
    'type' => '_doc',//数据表
    'body' => [
        'query' => [//查询字段
            'match' => [
                'fang_name' => [
                    'query' => $fang_name
                ]
            ]
        ],
        "highlight" => [//搜索高亮显示
            "fields" => [
                "fang_name" => [
                    "pre_tags" => [
                        "<span style='color: red'>"
                    ],
                    "post_tags" => [
                        "</span>"
                    ]
                ]
            ]
        ],
    ],
    'size' => 10, //每页显示条数 $request->get('size',10)
    'from' => 0, //偏移量 $request->get('from',0)
];

//es搜索显示
$results = ElasticSearchBusiness::getInstance()->getEsFangData($params);

//处理es搜索后数据
foreach ($results['hits']['hits'] as $key => $item) {
    $results['hits']['hits'][$key]['_source']['id'] = $results['hits']['hits'][$key]['_id'];
    $results['hits']['hits'][$key]['_source']['fang_name'] = $item['highlight']['fang_name'][0];
}

$data = array_column($results['hits']['hits'], '_source');

return $data;