专栏首页Web技术布道师推荐18-Laravel scout 与 elasticsearch 案例

推荐18-Laravel scout 与 elasticsearch 案例

$ wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-5.5.1.zip
$ unzip elasticsearch-5.5.1.zip
$ cd elasticsearch-5.5.1/

接着,进入解压后的目录,运行以下的命令,尝试启动 elastic

$ ./bin/elasticsearch

注意:

初次安装,非常有可能会出现以下报错:

max virtual memory areas vm.maxmapcount [65530] is too low

运行以下命令即可解决:

$ sudo sysctl -w vm.max_map_count=262144

如果一切正常,elastic 默认会在本机的 9200 端口运行,请求该端口,会获得以下

$ curl localhost:9200

{
  "name" : "atntrTf",
  "cluster_name" : "elasticsearch",
  "cluster_uuid" : "tf9250XhQ6ee4h7YI11anA",
  "version" : {
    "number" : "5.5.1",
    "build_hash" : "19c13d0",
    "build_date" : "2017-07-18T20:44:24.823Z",
    "build_snapshot" : false,
    "lucene_version" : "6.6.0"
  },
  "tagline" : "You Know, for Search"
}

默认情况下,elastic 只允许本机访问,如果需要远程访问权限,需要修改 elastic 安装目录的 config/elasticserach.yml 文件,去掉 netword.host 的注释,将它的值 改为 0.0.0.0 ,然后重启 elastic

network.host: 0.0.0.0

上面代码中,设成 0.0.0.0 让任何人都可以访问。线上服务不要这样设置,要设成具体的 IP

基本概念

elastic 本质上是一个分布式数据库,允许多台服务器协同工作,每台服务器可以允许多个 elastic 实例,单个 elastic 实例称为一个节点,一组节点构成一个集群

它有一些重要的概念

  1. Index(索引)
  2. Type(类型)
  3. Document(文档)
  4. Shards(分片)
  5. Replicasedit(副本)

分片和副本暂时用不到,就简单的说明一下

- 副本是乘法,越多越浪费,但也越保险。
- 分片是除法,分片越多,单分片数据就越少也越分散。

由于里面的概念内容比较多,贴出两个讲解的非常好的博客:

  1. 阮一峰的讲解
  2. ElastSearch 的技术分析

看完了之后,我们可以用一个对比来了解一下其中重要的概念

- 关系型数据库 -> Databases(库) -> Tables(表) -> Rows(行) -> Columns(列)。
- Elasticsearch -> Indeces(索引) -> Types(类型) -> Documents(文档) -> Fields(属性)。

Elasticsearch 集群可以包含多个索引(indices)(数据库),每一个索引可以包含多个类型 (Types)(表),每一个类型包含多个文档(documents)(行),然后每个文档包含多个字段(Fields)(列)。

虽然这么类比,但是毕竟是两个差异化的产品,而且上面也说过在以后的版本中类型 (Types) 可能会被删除,所以一般我们创建索引都是一个种类对应一个索引。生鲜就创建商品的索引,生活用品就创建生活用品的索引,而不会说创建一个商品的索引,里面既包含生鲜的类型,又包含生活用品的类型。

Laravel scout 与 es

先安装 scout 包

composer require laravel/scout

再生成配置文件

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

config/app.php 的 provider 中,添加

Laravel\Scout\ScoutServiceProvider::class,
ScoutEngines\Elasticsearch\ElasticsearchProvider::class,

然后我们还需要在 scout.php 中,添加 es 的配置信息,在 algolia 后添加

'elasticsearch' => [
        'index' => env('ELASTICSEARCH_INDEX', 'dongdianyi'),
        'hosts' => [
            env('ELASTICSEARCH_HOST', 'http://127.0.0.1:9200'),
        ],
],

我们还需要使用到 GuzzleHttp

安装一下

composer require guzzlehttp/guzzle

开始写代码,需要先使用 command ,让 ES 初始化一些数据

php artisan make:command InitEs

贴出我的代码

<?php

namespace App\Console\Commands;

use GuzzleHttp\Client;
use Illuminate\Console\Command;

class ESInit extends Command
{

    protected $signature = 'es:init';

    protected $description = '初始化 es库';

    public function __construct()
    {
        parent::__construct();
    }

    public function handle()
    {
        $client = new Client();
        try {
            $this->createTemplate($client);
            $this->createIndex($client);
        } catch (\Exception $ex) {
            $ex->message();
        }
    }

    public function createTemplate(Client $client)
    {
        $url = config('scout.elasticsearch.hosts')[0] . '/_template/tmp';
        // 保证 template 不存在
        // $client->delete($url);
        $param = [
            'json' => [
                'template' => '*',
                'settings' => [
                    'number_of_shards' => 1,
                ],
                'mappings' => [
                    '_default_' => [
                        '_all'              => [
                            'enabled' => true,
                        ],
                        'dynamic_templates' => [
                            [
                                'strings' => [
                                    'match_mapping_type' => 'string',
                                    'mapping'            => [
                                        'type'         => 'text',
                                        'analyzer'     => 'ik_smart',
                                        'ignore_above' => 256,
                                        'fields'       => [
                                            'keyword' => [
                                                'type' => 'keyword',
                                            ],
                                        ],
                                    ],
                                ],
                            ],
                        ],
                    ],
                ],
            ],
        ];
        $client->put($url, $param);
        $this->info('elasticsearch template created done');
    }

    public function createIndex(Client $client)
    {
        // 创建 index
        $url = config('scout.elasticsearch.hosts')[0] . '/' . config('scout.elasticsearch.index');
        // 保证 index 不存在
        // $client->delete($url);
        $param = [
            'json' => [
                'settings' => [
                    'refresh_interval'   => '5s',
                    'number_of_shards'   => 1,
                    'number_of_replicas' => 0,
                ],
                'mappings' => [
                    '_default_' => [
                        '_all' => [
                            'enabled' => false,
                        ],
                    ],
                ],
            ],
        ];
        $client->put($url, $param);
        $this->info('elasticsearch index created done');
    }
}

然后,我们要规定,是那个模型需要被搜索

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;
use Laravel\Scout\Searchable;


class Article extends Model
{
    use Searchable;
    protected $table = 'posts';

    protected $fillable = [
        'url',
        'author',
        'title',
        'content',
        'post_date'
    ];

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

在模型里面,使用 Searchable 和重载 toSearchableArray 函数就可以了

然后使用命令

php artisan scout:import "App\Article"

将目前数据库中的数据,按照 toSearchableArray 的规则导入,导入完成就可以了

验证结果

es 和 scout 的步骤已经走完了,接下来就可以使用了

先定义 graphql 接口

searchArticles(keyWord: String!): [Article!]! @paginate(defaultCount: 10, builder: "App\\Article@searchArticles")

然后再解析

public function searchArticles($rootValue, array $args, GraphQLContext $context, ResolveInfo $resolveInfo)
    {
        $query = $args['keyWord'];
        return Article::search($query);
    }

完成!,这里例子中我使用的是 ik_smart ,会自动按照中文分词的最大粒度去匹配

本文分享自微信公众号 - PHP技术大全(phpgod)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-09-21

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 10 分钟掌握 MySQL 的索引查询优化技巧

    本文的内容是总结一些MySQL的常见使用技巧,以供没有DBA的团队参考。以下内容以MySQL5.5为准,如无特殊说明,存储引擎以InnoDB为准。

    猿哥
  • PHP 闭包及Closure类

    上面就是一个简单的匿名函数,定义一个函数体,将函数体赋值给一个变量(php5.3之后支持该写法)。

    猿哥
  • WebRTC:一个视频聊天的简单例子

    在前面的章节中,已经对WebRTC相关的重要知识点进行了介绍,包括涉及的网络协议、会话描述协议、如何进行网络穿透等,剩下的就是WebRTC的API了。

    猿哥
  • MySQL深入学习第十一篇-怎么给字符串字段加索引?

    现在,几乎所有的系统都支持邮箱登录,如何在邮箱这样的字段上建立合理的索引,是我们今天要讨论的问题。

    越陌度阡
  • SAP里主索引和二级索引区别

    透明表索引有两种:分别是主索引和二级索引。 主索引是在我们创建表激活后由系统自动创建的,这个我们不能修改;二级索引可以我们自己创建。 主索引是表的主键,二级...

    matinal
  • Elasticsearch 索引生命周期管理详解与实践汇总篇

    Elasticsearch 从版本6.8开始已经免费开放索引生命周期管理的功能,通过该功能我们可以实现日志索引不同阶段的细化管理进而达到实际需求。本文基于以往的...

    南非骆驼说大数据
  • 【SAP技巧】SAP里主索引和二级索引区别

    透明表索引有两种:分别是主索引和二级索引。 主索引是在我们创建表激活后由系统自动创建的,这个我们不能修改;二级索引可以我们自己创建。 主索引是表的主键,二级索引...

    matinal
  • C++核心准则编译边学-F.20 输出结果时更应该使用返回值而不是输出参数

    A return value is self-documenting, whereas a & could be either in-out or out-on...

    面向对象思考
  • 这句简单的sql,如何加索引?颠覆了我多年的认知

    不啰嗦,直接入正题。问题是这样的。请问下面的sql语句,要想加快查询速度,该怎么创建索引?以下,以mysql数据库为准。

    xjjdog
  • 一文彻底搞懂跳表的时间复杂度、实现原理以及应用场景

    跳表是一种神奇的数据结构,因为几乎所有版本的大学本科教材上都没有跳表这种数据结构,而且神书《算法导论》、《算法第四版》这两本书中也没有介绍跳表。但是跳表插入、删...

    zhisheng

扫码关注云+社区

领取腾讯云代金券