Elasticsearch 是一个分布式、可扩展、实时的搜索与数据分析引擎。
一、核心特点
- 分布式架构:Elasticsearch具有天然的分布式特性,支持水平扩展,能够处理PB级别的数据。
- 实时搜索与分析:为用户提供近实时的搜索和分析能力,支持复杂查询和聚合操作。
- 多数据类型支持:不仅支持全文搜索,还支持结构化搜索、数据分析、复杂的语言处理、地理位置和对象间关联关系等。
- 简单易用:通过隐藏Lucene的复杂性,提供一套简单一致的RESTful API,使得用户可以更方便地使用。
二、核心组件 - 索引(Index):Elasticsearch存储数据的地方,类似于关系数据库中的“数据库”或“表”。索引可以被分成分片(Shard),每个分片可以有0个或多个副本(Replica)
- . 文档(Document):Elasticsearch中的基本数据单位,类似于关系数据库中的“行”。文档以JSON格式存储,包含多个字段(Field)。
- 映射(Mapping):定义索引中文档的字段约束信息,类似于关系数据库中的表结构。
三、工作原理 - 数据写入:当用户提交数据到Elasticsearch时,数据会被分片和复制到不同的节点上,以确保数据的冗余和可靠性。
- 索引创建:Elasticsearch使用Lucene作为底层搜索引擎,通过创建倒排索引来加速数据的检索。倒排索引记录了单词到文档的对应关系,使得用户可以快速地找到包含特定单词的文档。
- 数据查询:当用户查询数据时,Elasticsearch会根据查询条件在倒排索引中查找匹配的文档,并根据权重对结果进行排序和打分,最终将结果返回给用户。
四、应用场景 - 搜索引擎:为电商网站、新闻网站等提供商品搜索、站内搜索、模糊查询、全文检索等服务。
- 日志分析:收集和分析系统日志、应用日志等,帮助开发人员快速定位问题和优化系统性能。
- 业务宽表:当数据库字段太多、查询太慢、索引无法再优化时,可以使用Elasticsearch作为非关系型数据库来存储和查询数据。
- 商业智能:结合其他大数据分析工具,为企业提供数据分析和决策支持服务。
五、优势 - 高可用性:通过分布式架构和自动故障转移机制,确保系统的高可用性。
- 可扩展性:支持水平扩展,能够随着数据量的增长而无缝增长。
- 实时性:提供近实时的搜索和分析能力,满足用户对数据实时性的需求。
- 灵活性:支持多种数据类型和复杂的查询操作,满足用户多样化的需求。
- 使用RESTful API来创建一个索引、添加文档、执行搜索查询以及删除索引
创建一个索引
curl -X PUT "localhost:9200/my_index" -H 'Content-Type: application/json' -d'
{
"mappings": {
"properties": {
"title": {
"type": "text"
}
}
}
}
'
插入文档
curl -X POST "localhost:9200/my_index/_doc/1" -H 'Content-Type: application/json' -d'
{
"title": "Elasticsearch Demo"
}
'
搜索文档
curl -X GET "localhost:9200/my_index/_search?q=title:Elasticsearch"
删除索引
curl -X DELETE "localhost:9200/my_index"
使用golang创建一个索引、添加一个文档、执行搜索查询以及删除索引。
package main
import (
"context"
"fmt"
"log"
"strings"
"github.com/elastic/go-elasticsearch/v8"
"github.com/elastic/go-elasticsearch/v8/esapi"
)
func main() {
// 创建Elasticsearch客户端配置,包括用户名和密码
cfg := elasticsearch.Config{
Addresses: []string{
"http://localhost:9200", // 替换为你的Elasticsearch实例地址
},
Username: "your-username", // 替换为你的Elasticsearch用户名
Password: "your-password", // 替换为你的Elasticsearch密码
}
// 创建Elasticsearch客户端
es, err := elasticsearch.NewClient(cfg)
if err != nil {
log.Fatalf("Error creating the client: %s", err)
}
// 创建索引
createIndexReq := esapi.IndicesCreateRequest{
Index: "my_index",
Body: strings.NewReader(`{"mappings":{"properties":{"title":{"type":"text"}}}}`),
}
res, err := createIndexReq.Do(context.Background(), es)
if err != nil {
log.Fatalf("Error creating the index: %s", err)
}
defer res.Body.Close()
fmt.Println("Index created:", res.Status())
// 添加文档
doc := map[string]interface{}{
"title": "Elasticsearch Demo",
}
indexReq := esapi.IndexRequest{
Index: "my_index",
DocumentID: "1",
Body: strings.NewReader(fmt.Sprintf(`%s`, mustMarshalJSON(doc))),
Refresh: "true", // 立即刷新索引以便查询
}
res, err = indexReq.Do(context.Background(), es)
if err != nil {
log.Fatalf("Error indexing the document: %s", err)
}
defer res.Body.Close()
fmt.Println("Document indexed:", res.Status())
// 执行搜索查询
searchReq := esapi.SearchRequest{
Index: []string{"my_index"},
Body: strings.NewReader(`{"query":{"match":{"title":"Elasticsearch"}}}`),
}
res, err = searchReq.Do(context.Background(), es)
if err != nil {
log.Fatalf("Error getting the response: %s", err)
}
defer res.Body.Close()
fmt.Println("Search response:", res.String())
// 删除索引
deleteIndexReq := esapi.IndicesDeleteRequest{
Index: []string{"my_index"},
}
res, err = deleteIndexReq.Do(context.Background(), es)
if err != nil {
log.Fatalf("Error deleting the index: %s", err)
}
defer res.Body.Close()
fmt.Println("Index deleted:", res.Status())
}
// mustMarshalJSON 将map转换为JSON字符串,如果出错则panic
func mustMarshalJSON(v interface{}) string {
data, err := json.Marshal(v)
if err != nil {
panic(err)
}
return string(data)
}