zoukankan      html  css  js  c++  java
  • PHP 中使用 ElasticSearch 的最佳实践(上)

    PHP 中使用 ElasticSearch 的最佳实践

    引言

    PHP 开发者其实使用到 ES 的情况并不多,因为开发的大多数项目可能都没有快速模糊搜索的需求。
    即使有这样的需求,用 MySQL 的 like 查询,就基本可以搞定需求了。
    也就没有必要杀鸡用宰牛刀,使用 ES 了。
    正是在这种情况下,导致很多的 PHP 开发者都没有接触过 ES。
    即使有一些对 ES 有兴趣的,也因为 ES 中文文档的缺乏,而放弃了。
    因此,接下来的这篇文章就类比 MySQL 来使用 ES,让大多数的 PHP 开发者能使用起 ES 来。

    注:ElasticSearch 在文中简称 ES。

    实现思路

    我先简单的描述一下需求:
    实现一个商品的搜索功能,只要含有搜索关键字词的就匹配,并且按照发布时间和价格倒序。

    我这里已经安装好 MySQL 和 ES 了。如果没有安装的同学,可以先自行安装。

    先在 MySQL 中创建一张数据表 product,建表语句如下:

    CREATE TABLE `product` (
    	`id` int(11) UNSIGNED PRIMARY KEY AUTO_INCREMENT COMMENT '商品 ID',
    	`title` varchar(64) NOT NULL DEFAULT '' COMMENT '商品名称',
            `long_title` varchar(64) NOT NULL DEFAULT '' COMMENT '商品长名称',
    	`sku` varchar(32) NOT NULL DEFAULT '' COMMENT '商品 SKU',
    	`price` decimal(4, 2) NOT NULL DEFAULT 0 COMMENT '商品价格',
    	`sales` int(11) NOT NULL DEFAULT 0 COMMENT '商品销量',
    	`created_at` datetime COMMENT '创建时间',
    	`updated_at` datetime COMMENT '修改时间'
    ) ENGINE = InnoDB CHARACTER SET = utf8mb4;
    

    然后对应在 ES 中创建索引 product

    // 创建索引并定义属性
    PUT http://127.0.0.1/product
    
    {
     "settings": {
         "number_of_shards": 1,
         "number_of_replicas": 1
     },
     "mappings": {
         "properties": {
             "product_id": {
                 "type": "integer"
             },
             "title" : {
                 "type": "text"
             },
             "long_title" : {
                 "type": "text"
             },
             "sku": {
                 "type": "text"
             },
             "price": {
                 "type": "double"
             },
             "sales": {
                 "type": "integer"
             },
             "created_at": {
                 "type": "date",
                 "format": "yyyy-MM-dd HH:mm:ss || yyyy-MM-dd || epoch_millis"
             },
             "updated_at": {
                 "type": "date",
                 "format": "yyyy-MM-dd HH:mm:ss || yyyy-MM-dd || epoch_millis"
             }
         }
     }
    }
    

    创建好索引之后,我们就从 MySQL 将数据同步到 ES,同步的方案有如下三种:
    1、可以直接在存储入 MySQL 之后,就直接写入 ES。
    2、通过 Logstash 定时,从 MySQL 数据库中拉取数据同步到 ES。
    3、可以通过第三方中间件(例如:canal、go-mysql-elasticsearch),拉取 MySQL 的 binlog 日志,之后中间件解析日志将数据同步到 ES。

    创建好索引和添加数据之后,在业务的发展过程中,可能会增加字段。
    这里增加一个 description 字段。

    现在 MySQL 中增加字段到 product 数据表。

    alter table `product` add column description varchar(255) default "" comment "商品描述";
    

    然后向 ES 中的 product 索引,增加属性字段。

    // 增加映射字段
    // http://127.0.0.1:9200/product/_mapping
    {
    	"properties": {
    		"description": {
    			"type": "text"
    		}
    	}
    }   
    

    业务发展到中后时期的时候,可能发现字段越来越多了,这个时候想要删除一些字段。
    但是,在 ES 中的 Mapping 中是不能直接删除字段的,只能重新创建。
    很多情况,我们还是不建议去删除字段,因为这会增加很多不必要的成本以及带来的风险。
    如果,为了节省存储空间,Boss 一定要删除字段。那就按照下面的方法,也是可以实现的。

    1、创建一个新的索引
    2、创建新的映射关系 mapping
    3、将原索引的数据到入到新索引
    4、新索引创建原索引一致的别名
    5、删除原索引

    下一篇文章,我将会介绍如何在 laravel 框架中使用 ES。

  • 相关阅读:
    1013:温度表达转化
    1012:计算多项式的值
    1012:计算多项式的值
    1012:计算多项式的值
    数据结构——线性表
    数据结构——线性表
    数据结构——线性表
    SqlSever查询某个表的列名称、说明、备注、注释,类型等
    SqlSever查询某个表的列名称、说明、备注、注释,类型等
    SQL:将查询结果插入到另一个表的三种情况
  • 原文地址:https://www.cnblogs.com/yxhblogs/p/13339705.html
Copyright © 2011-2022 走看看