基于MySQL与Elasticsearch集成的完整示例代码,包含商品表结构、数据同步逻辑和搜索功能实现
关键实现要点说明:
MySQL表设计包含所有必要字段,updated_at字段用于增量同步
Elasticsearch映射配置了中文分词器(ik_max_word)支持中文搜索
同步方案采用全量+增量模式,可通过MySQL触发器实时调用
搜索功能支持关键词匹配和精确筛选组合查询
product.sql
- CREATE TABLE `products` (
- `id` INT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
- `name` VARCHAR(100) NOT NULL COMMENT '商品名称',
- `price` DECIMAL(10,2) NOT NULL COMMENT '价格',
- `attributes` TEXT COMMENT '属性JSON(支持关键词搜索)',
- `category` VARCHAR(50) NOT NULL COMMENT '商品类型',
- `is_sold` TINYINT(1) DEFAULT 0 COMMENT '是否售出',
- `updated_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
- ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
复制代码 es_index.php
- <?php
- require 'vendor/autoload.php';
- use Elasticsearch\ClientBuilder;
- $client = ClientBuilder::create()->setHosts(['localhost:9200'])->build();
- // 创建商品索引
- $params = [
- 'index' => 'products',
- 'body' => [
- 'settings' => [
- 'number_of_shards' => 1,
- 'number_of_replicas' => 0
- ],
- 'mappings' => [
- 'properties' => [
- 'name' => ['type' => 'text', 'analyzer' => 'ik_max_word'],
- 'price' => ['type' => 'float'],
- 'attributes' => ['type' => 'text', 'analyzer' => 'ik_max_word'],
- 'category' => ['type' => 'keyword'],
- 'is_sold' => ['type' => 'boolean']
- ]
- ]
- ]
- ];
- $response = $client->indices()->create($params);
复制代码 sync.php
- <?php
- require 'vendor/autoload.php';
- use Elasticsearch\ClientBuilder;
- class ProductSync {
- private $es;
- private $pdo;
-
- public function __construct() {
- $this->es = ClientBuilder::create()->setHosts(['localhost:9200'])->build();
- $this->pdo = new PDO('mysql:host=localhost;dbname=test', 'user', 'password');
- }
- // 全量同步
- public function fullSync() {
- $stmt = $this->pdo->query("SELECT * FROM products");
- while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
- $this->syncToEs($row);
- }
- }
- // 增量同步(通过触发器调用)
- public function syncProduct($productId) {
- $stmt = $this->pdo->prepare("SELECT * FROM products WHERE id = ?");
- $stmt->execute([$productId]);
- $row = $stmt->fetch(PDO::FETCH_ASSOC);
- $this->syncToEs($row);
- }
- private function syncToEs($product) {
- $params = [
- 'index' => 'products',
- 'id' => $product['id'],
- 'body' => [
- 'name' => $product['name'],
- 'price' => (float)$product['price'],
- 'attributes' => $product['attributes'],
- 'category' => $product['category'],
- 'is_sold' => (bool)$product['is_sold']
- ]
- ];
- $this->es->index($params);
- }
- }
- // 使用示例
- $sync = new ProductSync();
- $sync->fullSync();
复制代码 search.php
- <?php
- require 'vendor/autoload.php';
- use Elasticsearch\ClientBuilder;
- class ProductSearch {
- private $es;
-
- public function __construct() {
- $this->es = ClientBuilder::create()->setHosts(['localhost:9200'])->build();
- }
- public function search($keyword, $filters = []) {
- $must = [];
-
- // 关键词搜索(名称和属性)
- if (!empty($keyword)) {
- $must[] = [
- 'multi_match' => [
- 'query' => $keyword,
- 'fields' => ['name^3', 'attributes']
- ]
- ];
- }
- // 精确筛选
- foreach ($filters as $field => $value) {
- if (!empty($value)) {
- $must[] = ['term' => [$field => $value]];
- }
- }
- $params = [
- 'index' => 'products',
- 'body' => [
- 'query' => [
- 'bool' => ['must' => $must]
- ]
- ]
- ];
- return $this->es->search($params);
- }
- }
- // 使用示例
- $search = new ProductSearch();
- // 搜索名称/属性含"手机"且类型为"电子产品"的商品
- $results = $search->search('手机', ['category' => '电子产品']);
- print_r($results);
复制代码

以下是更多实用的商品搜索实现示例,结合MySQL与Elasticsearch同步场景:
一、多维度组合搜索示例
// 搜索关键词为"防水",筛选电子类目、价格100-500元、未售出的商品
$params = [
'index' => 'products',
'body' => [
'query' => [
'bool' => [
'must' => [
['multi_match' => ['query' => "防水", 'fields' => ['name','attributes']],
['term' => ['category' => "电子产品"]],
['term' => ['is_sold' => false]]
],
'filter' => [
['range' => ['price' => ['gte' => 100, 'lte' => 500]]]
]
]
]
]
];
逻辑说明:
must子句处理关键词匹配和精确筛选(类目/售出状态)
filter子句处理数值范围查询(不参与相关性评分)
二、权重优化搜索(爆款商品优先)
// 提升销量高、上架时间新的商品权重
$params = [
'query' => [
'function_score' => [
'query' => ['match' => ['name' => "蓝牙耳机"]],
'functions' => [
['field_value_factor' => ['field' => 'sales', 'factor' => 0.1]], // 销量权重
['gauss' => ['created_at' => ['origin' => 'now', 'scale' => '30d']]] // 新商品加分
]
]
]
];
适用场景:促销活动页,需同时考虑相关性和商品热度
三、属性聚合分析(生成商品筛选面板)
// 获取类目分布和价格区间
$params = [
'size' => 0,
'aggs' => [
'category_stats' => ['terms' => ['field' => 'category']],
'price_ranges' => ['range' => ['field' => 'price', 'ranges' => [
['to' => 100], ['from' => 100, 'to' => 500], ['from' => 500]
]]]
]
];
返回值示例:
"aggregations": {
"category_stats": {
"buckets": [{"key":"电子产品","doc_count":42}]
},
"price_ranges": {
"buckets": [{"to":100,"doc_count":31}]
}
}
作用:生成前端筛选器的动态数据源
四、拼写容错搜索
$params = [
'query' => [
'match' => [
'name' => [
'query' => "华wei手机",
'fuzziness' => 'AUTO' // 自动纠错
]
]
]
];
效果:可匹配"华为手机"等近似词组,提升搜索体验
(此处插入商品搜索优化案例卡片)
</noteList>
五、实时库存同步方案
// MySQL触发器(商品售出时立即同步)
DELIMITER $$
CREATE TRIGGER after_sale_update
AFTER UPDATE ON products
FOR EACH ROW
BEGIN
IF NEW.is_sold != OLD.is_sold THEN
CALL sync_to_es(NEW.id); // 调用存储过程同步
END IF;
END$$
DELIMITER ;
优势:确保库存状态的实时性,避免超卖
提示:实际部署时需注意
中文分词优化:安装IK分词器并配置自定义词典
压力测试:针对bulk操作调整刷新间隔(refresh_interval)
监控:通过Kibana跟踪搜索QPS和延迟指标

以下是MySQL存储过程sync_to_es的完整实现代码,用于将指定商品ID的数据实时同步到Elasticsearch:sync_to_es.sql
游客,本帖隐藏的内容需要积分高于 10 才可浏览,您当前积分为 0
该存储过程通过sys_exec调用外部PHP脚本实现同步,需确保MySQL服务器有执行系统命令权限。 配套的PHP同步脚本示例: sync_script.php 游客,本帖隐藏的内容需要积分高于 10 才可浏览,您当前积分为 0
该方案通过MySQL触发器+存储过程+PHP脚本实现准实时同步,需在MySQL中安装sys_exec UDF函数
|