背景
电商业务在过去的几年中呈现出快速增长的趋势,这导致了数据量的增加,同时也带来了数据处理和搜索的挑战。传统的关系型数据库在处理大量数据和高并发访问时,可能会遇到性能瓶颈和查询速度问题。因此,需要一种高性能、高可扩展性的搜索引擎来满足电商业务的需求。
简介
Elasticsearch 是一个基于 Lucene 构建的开源、分布式、RESTful 接口的全文搜索引擎,其每个字段均可被索引,且能够横向扩展至数以百计的服务器存储以及处理 TB 级的数据,其可以在极短的时间内存储、搜索和分析大量的数据。
作为一款基于RESTful API的分布式服务,Elasticsearch可以快速地、近乎于准实时地存储、查询和分析超大数据集,通常被用来作为构建复杂查询特性和需求强大应用的基础引擎或技术。
由于其强大的搜索能力、灵活的扩展性和丰富的功能特性,Elasticsearch在数据分析和搜索领域非常受欢迎。
基础知识
概念
- 节点和集群:理解Elasticsearch中的节点(Node)和集群(Cluster)的概念,以及它们如何协同工作。
- 索引(Index):索引是Elasticsearch中的核心概念,与关系型数据库中的数据库相似,但有其特殊性。
- 类型(Type)和文档(Document):在Elasticsearch 7.x之后,一个索引中只允许有一个类型,到Elasticsearch 8.x之后类型已经被移除,但了解其历史概念对理解Elasticsearch的发展有帮助。
- 分片(Shard)和副本(Replica):理解分片和副本的概念对于掌握Elasticsearch的数据分布和容错机制至关重要。
数据索引
- 文档映射(Mapping):学习如何定义文档的字段类型、分析器等属性。
- 索引管理:包括创建索引、更新映射、删除索引等操作。
搜索技术
- 查询DSL:Elasticsearch提供了一种丰富的查询DSL(Domain Specific Language),用于执行复杂的搜索操作。
- 聚合(Aggregations):聚合提供了从数据中提取洞察力的能力,类似于SQL中的GROUP BY操作。
ElasticSearch与传统搜索引擎
ElasticSearch与传统搜索引擎的主要区别在于数据存储和查询方式。传统搜索引擎通常采用基于文件系统的数据存储,并使用自然语言处理技术进行查询。而ElasticSearch则采用基于内存的数据存储,并使用Lucene库进行查询。这使得ElasticSearch具有更高的查询速度和可扩展性。
索引和查询的基本原理
ElasticSearch的核心原理是基于Lucene库的索引和查询机制。索引是将文档存储在磁盘上的过程,查询是从索引中搜索文档的过程。
索引的基本原理
索引的过程包括以下步骤:
- 文档解析:将文档中的字段和值解析成一个内部表示。
- 分析:将文本字段通过分析器转换为索引用的形式。
- 存储:将解析和分析后的内容存储到磁盘上的索引文件中。
查询的基本原理
查询的过程包括以下步骤:
- 解析:将查询请求解析成一个查询对象。
- 搜索:根据查询对象从索引中搜索匹配的文档。
- 排序:将搜索出的文档按照排序规则进行排序。
- 高亮:将查询关键词标注为高亮显示。
具体操作步骤
- 安装和配置:安装ElasticSearch并配置相关参数。
- 创建索引:创建一个索引,用于存储文档。
- 添加文档:将文档添加到索引中。
- 查询文档:根据查询条件搜索文档。
- 更新文档:更新文档的内容。
- 删除文档:删除文档。
- 查询分析:查看查询的分析结果。
最佳实践
安装和配置
这里的ElasticSearch搜索服务直接使用阿里云Elasticsearch。阿里云Elasticsearch是基于开源Elasticsearch构建的全托管Elasticsearch云服务,在100%兼容开源功能的同时,支持开箱即用。
客户端SDK安装
这里使用Elasticsearch PHP客户端。
代码语言:javascript复制composer require elasticsearch/elasticsearch
配置Elasticsearch
案例客户端ElasticSearchCLient
<?php
/**
* @desc ElasticSearchCLient
* @author Tinywan(ShaoBo Wan)
*/
declare(strict_types=1);
namespace search;
use ElasticsearchClient;
use ElasticsearchConnectionPoolSimpleConnectionPool;
class ElasticSearchCLient
{
/**
* @var Client|null
*/
protected static ?Client $instance = null;
private function __construct()
{
echo 'I am Constructed';
}
/**
* @desc: 实例
* @return Client|null
*/
public static function getInstance(): ?Client
{
if (is_null(self::$instance)) {
static::$instance = ElasticsearchClientBuilder::create()
->setHosts([
[
'host' => '127.0.0.1',
'port' => '9200',
'scheme' => 'http',
'user' => 'elastic',
'pass' => 'elastic'
]
])
->setConnectionPool(SimpleConnectionPool::class)
->setRetries(10)
->build();
}
return static::$instance;
}
}
文档模型
定义一个简单的文档模型
创建一个文档索引
代码语言:javascript复制/**
* @desc 创建一个索引
* @return Response
* @author Tinywan(ShaoBo Wan)
*/
public function createIndex(): Response
{
$client = ElasticSearchCLient::getInstance();
$indexParams = [
'index' => 'resty_product_test_index', // 索引名称
];
$indexResponse = $client->indices()->create($indexParams);
return response_json('success',0,$indexResponse);
}
添加文档到ES
代码语言:javascript复制/**
* @desc 添加文档到Elasticsearch
* @return Response
* @author Tinywan(ShaoBo Wan)
*/
public function addDocument(): Response
{
$client = ElasticSearchCLient::getInstance();
$data = [
'id' => 20245,
'title' => '开源技术小栈20245直播间',
'content' => '开源技术小栈-腾讯云开发者社区,开源技术小栈20245直播间',
];
$indexParams = [
'index' => 'resty_product_test_index', // 索引名称
'id' => $data['id'], // 文档ID
'body' => $data,
'client' => [
'timeout' => 10,
'connect_timeout' => 10
]
];
$indexResponse = $client->index($indexParams);
return response_json('success',0,$indexResponse);
}
响应结果
代码语言:javascript复制{
"code": 0,
"msg": "success",
"data": {
"_index": "resty_product_test_index",
"_type": "_doc",
"_id": "20245",
"_version": 1,
"result": "created",
"_shards": {
"total": 2,
"successful": 2,
"failed": 0
},
"_seq_no": 4,
"_primary_term": 1
}
}
搜索文档
代码语言:javascript复制/**
* @desc 搜索文档
* @return Response
* @author Tinywan(ShaoBo Wan)
*/
public function searchDocument(): Response
{
$client = ElasticSearchCLient::getInstance();
$query = '开源技术小栈';
$indexParams = [
'index' => 'resty_product_test_index',
'body' => [
'query' => [
'multi_match' => [
'query' => $query,
'fields' => ['title', 'content'],
]
]
]
];
$indexResponse = $client->search($indexParams);
return response_json('success',0,$indexResponse);
}
搜索结果
代码语言:javascript复制{
"took": 12,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 2,
"relation": "eq"
},
"max_score": 1.5399661,
"hits": [
{
"_index": "resty_product_test_index",
"_type": "_doc",
"_id": "2024",
"_score": 1.5399661,
"_source": {
"id": 2024,
"title": "开源技术小栈20240724直播间",
"content": "开源技术小栈-腾讯云开发者社区,开源技术小栈20240724直播间"
}
},
{
"_index": "resty_product_test_index",
"_type": "_doc",
"_id": "20245",
"_score": 1.5399661,
"_source": {
"id": 20245,
"title": "开源技术小栈20245直播间",
"content": "开源技术小栈-腾讯云开发者社区,开源技术小栈20245直播间"
}
}
]
}
}