package main
import (
"context"
"encoding/json"
"fmt"
"log"
"time"
"github.com/olivere/elastic/v7"
)
// 定义一个员工结构体
type Employee struct {
Firstname string `json:"firstname"`
Lastname string `json:"lastname"`
Age int `json:"age"`
About string `json:"about"`
Interests []string `json:"interests"`
Metadata map[string]interface{} `json:"metadata,omitempty"`
}
func main() {
// 创建 Elasticsearch 客户端
client, err := elastic.NewClient(
elastic.SetURL("http://localhost:9200"),
elastic.SetSniff(false), // 在生产环境中根据需要设置
elastic.SetHealthcheck(true),
)
if err != nil {
log.Fatal("创建 Elasticsearch 客户端失败:", err)
}
// 检查 Elasticsearch 集群是否可用
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
info, code, err := client.Ping("http://localhost:9200").Do(ctx)
if err != nil {
log.Fatal("连接 Elasticsearch 集群失败:", err)
}
fmt.Printf("Elasticsearch 返回 code: %d, version: %s\n", code, info.Version.Number)
// 获取 Elasticsearch 版本号
esversion, err := client.ElasticsearchVersion("http://localhost:9200")
if err != nil {
log.Fatal("获取 Elasticsearch 版本失败:", err)
}
fmt.Printf("Elasticsearch 版本: %s\n", esversion)
// 创建索引
indexName := "employees"
createIndex(client, indexName)
// 添加文档
addDocument(client, indexName)
// 批量添加文档
bulkAddDocuments(client, indexName)
// 查询文档
searchDocuments(client, indexName)
// 更新文档
updateDocument(client, indexName)
// 删除文档
deleteDocument(client, indexName)
// 删除索引
deleteIndex(client, indexName)
}
// 创建索引
func createIndex(client *elastic.Client, indexName string) {
ctx := context.Background()
// 检查索引是否已存在
exists, err := client.IndexExists(indexName).Do(ctx)
if err != nil {
log.Fatal("检查索引存在性失败:", err)
}
if exists {
fmt.Printf("索引 %s 已存在,正在删除...\n", indexName)
_, err = client.DeleteIndex(indexName).Do(ctx)
if err != nil {
log.Fatalln("删除索引失败")
}
}
// 创建新索引
// 定义索引映射
mapping := `{
"settings":{
"number_of_shards":1,
"number_of_replicas":0
},
"mappings":{
"properties":{
"firstname":{
"type":"text"
},
"lastname":{
"type":"text"
},
"age":{
"type":"integer"
},
"about":{
"type":"text"
},
"interests":{
"type":"keyword"
},
"metadata":{
"type":"object",
"dynamic": true
}
}
}
}`
createIndex, err := client.CreateIndex(indexName).BodyString(mapping).Do(ctx)
if err != nil {
log.Fatal("创建索引失败:", err)
}
if !createIndex.Acknowledged {
log.Fatal("创建索引未被确认")
}
fmt.Printf("成功创建索引: %s\n", indexName)
}
// 添加单个文档
func addDocument(client *elastic.Client, indexName string) {
ctx := context.Background()
// 创建员工实例
employee := Employee{
Firstname: "John",
Lastname: "Doe",
Age: 35,
About: "I love to go rock climbing",
Interests: []string{"sports", "music"},
Metadata: map[string]interface{}{
"created_by": "system",
"timestamp": time.Now().Unix(),
},
}
// 添加文档
put, err := client.Index().
Index(indexName).
BodyJson(employee).
Do(ctx)
if err != nil {
log.Fatal("添加文档失败:", err)
}
fmt.Printf("添加文档成功,ID: %s\n", put.Id)
}
// 批量添加文档
func bulkAddDocuments(client *elastic.Client, indexName string) {
ctx := context.Background()
// 创建批量处理服务
bulkRequest := client.Bulk()
// 准备批量数据
employees := []Employee{
{
Firstname: "Jane",
Lastname: "Smith",
Age: 32,
About: "I like to collect rock albums",
Interests: []string{"music"},
Metadata: map[string]interface{}{
"created_by": "system",
"timestamp": time.Now().Unix(),
},
},
{
Firstname: "Douglas",
Lastname: "Home",
Age: 28,
About: "Rock climber and skateboarder",
Interests: []string{"sports", "extreme"},
Metadata: map[string]interface{}{
"created_by": "admin",
"timestamp": time.Now().Unix(),
},
},
}
// 添加到批量请求
for _, emp := range employees {
doc := elastic.NewBulkIndexRequest().
Index(indexName).
Doc(emp)
bulkRequest = bulkRequest.Add(doc)
}
// 执行批量操作
bulkResponse, err := bulkRequest.Do(ctx)
if err != nil {
log.Fatal("批量添加文档失败:", err)
}
if bulkResponse.Errors {
log.Fatal("批量添加文档出现错误")
}
fmt.Printf("批量添加 %d 个文档成功\n", len(employees))
}
// 查询文档
func searchDocuments(client *elastic.Client, indexName string) {
ctx := context.Background()
// 简单查询所有文档
fmt.Println("\n查询所有文档:")
searchResult, err := client.Search().
Index(indexName).
Do(ctx)
if err != nil {
log.Fatal("查询文档失败:", err)
}
fmt.Printf("查询到 %d 个文档\n", searchResult.TotalHits())
if searchResult.TotalHits() > 0 {
for _, hit := range searchResult.Hits.Hits {
var emp Employee
err := json.Unmarshal(hit.Source, &emp)
if err != nil {
log.Fatal("解析文档失败:", err)
}
fmt.Printf("ID: %s, 姓名: %s %s, 年龄: %d\n", hit.Id, emp.Firstname, emp.Lastname, emp.Age)
}
}
// 使用查询条件搜索
fmt.Println("\n搜索对运动感兴趣的员工:")
termQuery := elastic.NewTermQuery("interests", "sports")
searchResult, err = client.Search().
Index(indexName).
Query(termQuery).
Do(ctx)
if err != nil {
log.Fatal("条件查询失败:", err)
}
fmt.Printf("找到 %d 个对运动感兴趣的员工\n", searchResult.TotalHits())
for _, hit := range searchResult.Hits.Hits {
var emp Employee
err := json.Unmarshal(hit.Source, &emp)
if err != nil {
log.Fatal("解析文档失败:", err)
}
fmt.Printf("ID: %s, 姓名: %s %s, 兴趣: %v\n", hit.Id, emp.Firstname, emp.Lastname, emp.Interests)
}
}
// 更新文档
func updateDocument(client *elastic.Client, indexName string) {
ctx := context.Background()
// 首先查找一个文档
searchResult, err := client.Search().
Index(indexName).
Size(1).
Do(ctx)
if err != nil {
log.Fatal("查找文档失败:", err)
}
if searchResult.TotalHits() > 0 {
hit := searchResult.Hits.Hits[0]
// 更新文档
update, err := client.Update().
Index(indexName).
Id(hit.Id).
Doc(map[string]interface{}{"age": 30}).
Do(ctx)
if err != nil {
log.Fatal("更新文档失败:", err)
}
fmt.Printf("更新文档成功,ID: %s, 新版本: %d\n", update.Id, update.Version)
}
}
// 删除文档
func deleteDocument(client *elastic.Client, indexName string) {
ctx := context.Background()
// 查找一个文档进行删除
searchResult, err := client.Search().
Index(indexName).
Size(1).
Do(ctx)
if err != nil {
log.Fatal("查找文档失败:", err)
}
if searchResult.TotalHits() > 0 {
hit := searchResult.Hits.Hits[0]
// 删除文档
d, err := client.Delete().
Index(indexName).
Id(hit.Id).
Do(ctx)
if err != nil {
log.Fatal("删除文档失败:", err)
}
fmt.Printf("删除文档成功,ID: %s\n", d.Id)
}
}
// 删除索引
func deleteIndex(client *elastic.Client, indexName string) {
ctx := context.Background()
// 删除索引
deleteIndex, err := client.DeleteIndex(indexName).Do(ctx)
if err != nil {
log.Fatal("删除索引失败:", err)
}
if !deleteIndex.Acknowledged {
log.Fatal("删除索引未被确认")
}
fmt.Printf("成功删除索引: %s\n", indexName)
}