乐趣区

关于laravel:在Laravel项目中使用Elasticsearch

Elasticsearch 概念

Elasticsearch 是一个基于 Lucene 的搜寻服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于 RESTful web 接口。Elasticsearch 是用 Java 语言开发的,并作为 Apache 许可条款下的开放源码公布,是一种风行的企业级搜索引擎。Elasticsearch 用于云计算中,可能达到实时搜寻,稳固,牢靠,疾速,装置使用方便。官网客户端在 Java、.NET(C#)、PHP、Python、Apache Groovy、Ruby 和许多其余语言中都是可用的。

Elastic 的底层是开源库 Lucene。然而,你没法间接用 Lucene,必须本人写代码去调用它的接口。Elastic 是 Lucene 的封装,提供了 REST API 的操作接口,开箱即用。

装置 Elasticsearch

参考装置 Elasticsearch
我应用 centos 服务器,装置命令如下

# Download and install the public signing key:
$ rpm --import https://artifacts.elastic.co/GPG-KEY-elasticsearch

# 增加 yum 源
$ vim /etc/yum.repos.d/elasticsearch-7.x.repo
# 要增加的内容 ##################################################################
[elasticsearch-7.x] 
name=Elasticsearch repository for  7.x packages
baseurl=https://artifacts.elastic.co/packages/7.x/yum
gpgcheck=1 
gpgkey=https://artifacts.elastic.co/GPG-KEY-elasticsearch
enabled=1 
autorefresh=1 
type=rpm-md
###############################################################################

# 装置 es
$ yum install -y elasticsearch

# 治理 es
$ systemctl start elasticsearch.service
$ systemctl stop elasticsearch.service

# 测试 elasticsearch
# 参考 https://www.elastic.co/guide/cn/elasticsearch/guide/current/running-elasticsearch.html
$ curl http://127.0.0.1:9200?pretty 

外网拜访 Elasticsearch

参考这两篇文章 elasticsearch 外网拜访设置,elasticsearch 装置及启动异样解决

默认状况下装置 elasticsearch 之后是无奈进行外网拜访的,能够通过设置来实现这一目标

1、编辑 elasticsearch 配置文件:vim /etc/config/elasticsearch.yml

找到 network.host 这一行,更改为 network.host: 0.0.0.0

2、重启服务,发现报错

ERROR: [1] bootstrap checks failed

3、以 root 账户更改 /etc/sysctl.conf 文件,增加如下内容

vm.max_map_count=655360

4、以 root 账户执行上面命令

[*@elk01 ~]$ sudo sysctl -p
vm.max_map_count = 655360

5、再次启动服务,凋谢 9200 端口。仍然会报错 ERROR: [1] bootstrap checks failed

6、在 elasticsearch.yml 中增加配置项:

bootstrap.memory_lock: false
bootstrap.system_call_filter: false

cluster.initial_master_nodes: [“node-1”]
这个的话,这里的 node- 1 是下面一个默认的记得关上就能够了

7、再次重启服务,胜利开启 es 服务

通过网址也能够间接拜访 elasticsearch, 示意咱们曾经能够胜利从外网拜访,当然在正式环境中,还是须要配置 ip 限度拜访的,我这边是不便测试,所有暂不限度。

Elasticsearch 根底概念和应用

内容参考 Elasticsearch 根底概念,全文搜索引擎 Elasticsearch 入门教程
Elasticsearch 实质上是一个数据库,但并不是 MySQL 这种关系型数据库,查询语言也不是 SQL,而是 Elasticsearch 本人的一套查询语言。

既然是数据库,有一些概念是互通的,如下表:

MySQL Elasticsearch
数据库(Database) 索引(Index)
表(Table) 类型(Type)
记录(Row) 文档(Document)
字段(Column) 字段(Fields)

创立索引

创立名为 test 的索引

curl -X PUT http://localhost:9200/test

服务器返回一个 JSON 对象,外面的 acknowledged 字段示意操作胜利。

{"acknowledged":true,"shards_acknowledged":true,"index":"test"}

删除索引

curl -X DELETE 'localhost:9200/test'

服务器返回值为,外面的 acknowledged 字段示意操作胜利

{"acknowledged": true}

查看索引

curl -X GET 'http://localhost:9200/_cat/indices?v'

服务器会列出所有索引

health status index uuid                   pri rep docs.count docs.deleted store.size pri.store.size
yellow open   test  y6f8oZitQEKE3blusrH_7g   1   1          0            0       208b           208b

新增数据

向指定的 /Index/Type 发送 PUT 申请,就能够在 Index 外面新增一条记录。比方,向 /accounts/person 发送申请,就能够新增一条人员记录。

curl -H 'Content-Type: application/json' -X PUT 'localhost:9200/accounts/person/1' -d '{"user":" 张三 ","title":" 工程师 ","desc":" 数据库治理 "}'

服务器响应后返回 json 对象如下: 会给出 Index、Type、Id、Version 等信息

{
    "_index":"accounts",
    "_type":"person",
    "_id":"1",
    "_version":1,
    "result":"created",
    "_shards":{"total":2,"successful":1,"failed":0},
    "_seq_no":0,
    "_primary_term":1
}

如果你认真看,会发现申请门路是 /accounts/person/1,最初的1 是该条记录的 Id。它不肯定是数字,任意字符串(比方abc)都能够。

新增记录的时候,也能够不指定 Id,这时要改成 POST 申请。

curl -H 'Content-Type: application/json' -X POST 'localhost:9200/accounts/person' -d '{"user":" 李四 ","title":" 工程师 ","desc":" 系统管理 "}'

服务器返回 json 如下:_id 字段就是一个随机字符串

{
    "_index":"accounts",
    "_type":"person",
    "_id":"0JO3x3MBEaLkjdo6ypYV",
    "_version":1,
    "result":"created",
    "_shards":{"total":2,"successful":1,"failed":0},
    "_seq_no":1,
    "_primary_term":1
}

查看记录

/Index/Type/Id 收回 GET 申请,就能够查看这条记录。

curl 'localhost:9200/accounts/person/1?pretty=true'

服务器返回 json 对象如下:URL 的参数 pretty=true 示意以易读的格局返回。

返回的数据中,found 字段示意查问胜利,_source 字段返回原始记录。

{
  "_index" : "accounts",
  "_type" : "person",
  "_id" : "1",
  "_version" : 1,
  "_seq_no" : 0,
  "_primary_term" : 1,
  "found" : true,
  "_source" : {
    "user" : "张三",
    "title" : "工程师",
    "desc" : "数据库治理"
  }
}

如果 Id 不正确,就查不到数据,found字段就是false

curl 'localhost:9200/accounts/person/2?pretty=true'

服务器返回 json 对象如下:

{
  "_index" : "accounts",
  "_type" : "person",
  "_id" : "2",
  "found" : false
}

删除记录

curl -X DELETE 'localhost:9200/accounts/person/0JO3x3MBEaLkjdo6ypYV'

服务器返回 json 对象如下:

{
    "_index":"accounts",
    "_type":"person",
    "_id":"0JO3x3MBEaLkjdo6ypYV",
    "_version":2,
    "result":"deleted",
    "_shards":{"total":2,"successful":1,"failed":0},
    "_seq_no":2,
    "_primary_term":1
}

若删除的数据不存在,咱们再执行一次下面的命令

curl -X DELETE 'localhost:9200/accounts/person/0JO3x3MBEaLkjdo6ypYV'

服务器返回 json 对象如下:result 返回后果为 not_found

{
    "_index":"accounts",
    "_type":"person",
    "_id":"0JO3x3MBEaLkjdo6ypYV",
    "_version":1,
    "result":"not_found",
    "_shards":{"total":2,"successful":1,"failed":0},
    "_seq_no":3,
    "_primary_term":1
}

更新数据

更新记录就是应用 PUT 申请,从新发送一次数据。

curl -H 'Content-Type: application/json' -X PUT 'localhost:9200/accounts/person/1' -d '{"user":" 张三 ","title":" 工程师 ","desc":" 数据库治理,软件开发 "}' 

服务器响应后返回 json 对象如下:result 后果返回 updated, 示意更新数据胜利

{
    "_index":"accounts",
    "_type":"person",
    "_id":"1",
    "_version":2,
    "result":"updated",
    "_shards":{"total":2,"successful":1,"failed":0},
    "_seq_no":4,
    "_primary_term":1
}

数据查问

返回所有记录

curl 'localhost:9200/accounts/person/_search?pretty=true'

服务器会返回索引类型下的所有数据,返回 json 如下:

{
  "took" : 7,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 1,
      "relation" : "eq"
    },
    "max_score" : 1.0,
    "hits" : [
      {
        "_index" : "accounts",
        "_type" : "person",
        "_id" : "1",
        "_score" : 1.0,
        "_source" : {
          "user" : "张三",
          "title" : "工程师",
          "desc" : "数据库治理,软件开发"
        }
      }
    ]
  }
}

下面代码中,返回后果的 took字段示意该操作的耗时(单位为毫秒),timed_out字段示意是否超时,hits字段示意命中的记录,外面子字段的含意如下。
返回的记录中,每条记录都有一个 _score 字段,示意匹配的程序,默认是依照这个字段降序排列。

全文搜寻

Elastic 的查问十分特地,应用本人的查问语法,要求 GET 申请带有数据体。

curl -H 'Content-Type: application/json' 'localhost:9200/accounts/person/_search?pretty=true'  -d '{"query": {"match": {"desc":" 软件 "}}
}'

服务器返回 json 对象如下:

{
  "took" : 3,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 1,
      "relation" : "eq"
    },
    "max_score" : 0.5753642,
    "hits" : [
      {
        "_index" : "accounts",
        "_type" : "person",
        "_id" : "1",
        "_score" : 0.5753642,
        "_source" : {
          "user" : "张三",
          "title" : "工程师",
          "desc" : "数据库治理,软件开发"
        }
      }
    ]
  }
}

下面代码应用 Match 查问,指定的匹配条件是 desc 字段外面蕴含 ” 软件 ” 这个词。返回后果如下。

Elastic 默认一次返回 10 条后果,能够通过 size 字段扭转这个设置。

$ curl -H 'Content-Type: application/json' 'localhost:9200/accounts/person/_search'  -d '{"query": {"match": {"desc":" 治理 "}},"size": 1
}'

下面代码指定,每次只返回一条后果。

还能够通过 from 字段,指定位移。

$ curl -H 'Content-Type: application/json' 'localhost:9200/accounts/person/_search'  -d '{"query": {"match": {"desc":" 治理 "}},"from": 1,"size": 1
}'

下面代码指定,从地位 1 开始(默认是从地位 0 开始),只返回一条后果。

如果有多个搜寻关键字,Elastic 认为它们是 or 关系。

$ curl -H 'Content-Type: application/json' 'localhost:9200/accounts/person/_search'  -d '{"query": {"match": {"desc":" 软件 零碎 "}}
}'

下面代码搜寻的是 软件 or 零碎

如果要执行多个关键词的 and 搜寻,必须应用布尔查问。

$ curl -H 'Content-Type: application/json' 'localhost:9200/accounts/person/_search'  -d '{"query": {"bool": {"must": [{ "match": { "desc": "软件"} },
        {"match": { "desc": "零碎"} }
      ]
    }
  }
}'

在 laravel 中应用 Elasticsearch

通过 composer 引入应用 Elasticsearch 第三方包

composer require babenkoivan/scout-elasticsearch-driver

Laravel 提供了一个扩大包 Scout 用来提供全文搜寻的性能,通过装置扩大包咱们是能够应用 Elasticsearch 作为驱动的。

文档可查看这里 babenkoivan/scout-elasticsearch-driver, 在应用扩大包之前,须要进行相干配置

配置

首先将 Scout 和扩大包的配置文件公布进去。

php artisan vendor:publish --provider="Laravel\Scout\ScoutServiceProvider"
php artisan vendor:publish --provider="ScoutElastic\ScoutElasticServiceProvider"

批改一下配置,能够配置到 env 中。

SCOUT_DRIVER=elastic 
SCOUT_ELASTIC_HOST=elasticsearch:9200

应用

创立索引

该命令会创立一个 GoodsIndexConfigurator.php 文件, 在文件中能够指定索引名称和设置

php artisan make:index-configurator Es/GoodsIndexConfigurator

该命令会在 elasticsearch 中创立相应的索引名,相当于创立在 mysql 中创立表

php artisan elastic:create-index App\\Es\\GoodsIndexConfigurator

留神,每个可搜寻模型都须要有本人的索引配置器。

在 Elasticsearch 6.0.0 或更高版本中创立的索引只能蕴含一个映射类型。在 5.x 中创立的具备多种映射类型的索引将持续像在 Elasticsearch 6.x 中一样工作。映射类型将在 Elasticsearch 7.0.0 中齐全删除。

批改商品模型代码如下

<?php

namespace App\Models;

use App\Es\GoodsIndexConfigurator;
use Illuminate\Database\Eloquent\Model;
use ScoutElastic\Searchable;

class HGoodsEs extends Model
{
    use Searchable;

    protected $table='goods';
    public $timestamps = true;

    // 应用 es 配置
    protected $indexConfigurator = GoodsIndexConfigurator::class;

    protected $mapping = [
        'properties' => [
            'title' => ['type' => 'text',],
            'content' => ['type' => 'text',],
        ]
    ];

    public function toSearchableArray()
    {
        return [
            'title'=> $this->title,
            'content' => strip_tags($this->content),
        ];
    }

}

数据导入

执行以下命令,导入商品数据

php artisan scout:import "App\Models\Goods"

导入实现后,咱们间接在网页查看 http://elasticsearch:9200/goods/goods/_search?pretty
可查看到如下:

阐明数据已胜利导入 elasticsearch

测试搜寻

应用 tinker 测试

Goods::search('boy')->get()

执行后果如下,阐明已胜利应用 elasticsearch 进行全文搜寻,其余就依据业务须要去执行相应的查问就好了

退出移动版