一架梯子,一头程序猿,仰望星空!

golang elasticsearch 文档操作(CRUD)


本节主要介绍go语言对Elasticsearch文档的基础操作:创建、查询、更新、删除。

为了方便演示文档的CRUD操作,我们先定义索引的struct结构

// 定义一个文章索引结构,用来存储文章内容
type Article struct {
	Title   string    // 文章标题
	Content string    // 文章内容
	Author  string    // 作者
	Created time.Time // 发布时间
}

添加文档

 package main

import (
	"context"
	"encoding/json"
	"fmt"
	"github.com/olivere/elastic/v7"
	"log"
	"os"
	"time"
)

type Article struct {
	Title   string    // 文章标题
	Content string    // 文章内容
	Author  string    // 作者
	Created time.Time // 发布时间
}


func main() {
        // 创建client连接ES
	client, err := elastic.NewClient(
		// elasticsearch 服务地址,多个服务地址使用逗号分隔
		elastic.SetURL("http://127.0.0.1:9200", "http://127.0.0.1:9201"),
		// 基于http base auth验证机制的账号和密码
		elastic.SetBasicAuth("user", "secret"),
		// 启用gzip压缩
		elastic.SetGzip(true),
		// 设置监控检查时间间隔
		elastic.SetHealthcheckInterval(10*time.Second),
		// 设置请求失败最大重试次数
		elastic.SetMaxRetries(5),
		// 设置错误日志输出
		elastic.SetErrorLog(log.New(os.Stderr, "ELASTIC ", log.LstdFlags)),
		// 设置info日志输出
		elastic.SetInfoLog(log.New(os.Stdout, "", log.LstdFlags)))

	if err != nil {
		// Handle error
		fmt.Printf("连接失败: %v\n", err)
	} else {
		fmt.Println("连接成功")
	}

	// 执行ES请求需要提供一个上下文对象
	ctx := context.Background()

	// 定义一篇博客
	blog := Article{Title:"golang es教程", Content:"go如何操作ES", Author:"tizi", Created:time.Now()}

	// 使用client创建一个新的文档
	put1, err := client.Index().
		Index("blogs"). // 设置索引名称
		Id("1"). // 设置文档id
		BodyJson(blog). // 指定前面声明struct对象
		Do(ctx) // 执行请求,需要传入一个上下文对象
	if err != nil {
		// Handle error
		panic(err)
	}

	fmt.Printf("文档Id %s, 索引名 %s\n", put1.Id, put1.Index)
}

提示:后续的章节不再重复给出完整的代码,仅给出关键代码片段

查询文档

根据文档ID,查询文档

// 根据id查询文档
get1, err := client.Get().
		Index("blogs"). // 指定索引名
		Id("1"). // 设置文档id
		Do(ctx) // 执行请求
if err != nil {
	// Handle error
	panic(err)
}
if get1.Found {
	fmt.Printf("文档id=%s 版本号=%d 索引名=%s\n", get1.Id, get1.Version, get1.Index)
}

# 手动将文档内容转换成go struct对象
msg2 := Article{}
// 提取文档内容,原始类型是json数据
data, _ := get1.Source.MarshalJSON()
// 将json转成struct结果
json.Unmarshal(data, &msg2)
// 打印结果
fmt.Println(msg2.Title)

批量查询文档

通过多个Id批量查询文档,对应ES的multi get

// 查询id等于1,2,3的博客内容
	result, err := client.MultiGet().
		Add(elastic.NewMultiGetItem(). // 通过NewMultiGetItem配置查询条件
			Index("blogs"). // 设置索引名
			Id("1")). // 设置文档id
		Add(elastic.NewMultiGetItem().Index("blogs").Id("2")).
		Add(elastic.NewMultiGetItem().Index("blogs").Id("3")).
		Do(ctx) // 执行请求
	
	if err != nil {
		panic(err)
	}

	// 遍历文档
	for _, doc := range result.Docs {
		// 转换成struct对象
		var content Article
		tmp, _ := doc.Source.MarshalJSON()
		err := json.Unmarshal(tmp, &content)
		if err != nil {
			panic(err)
		}

		fmt.Println(content.Title)
	}

更新文档

根据id更新文档

_, err := client.Update().
		Index("blogs"). // 设置索引名
		Id("1"). // 文档id
		Doc(map[string]interface{}{"Title": "新的文章标题"}). // 更新Title="新的文章标题",支持传入键值结构
		Do(ctx) // 执行ES查询
if err != nil {
   // Handle error
   panic(err)
}

根据条件更新文档

支持批量更新文档内容

_, err = client.UpdateByQuery("blogs").
                // 设置查询条件,这里设置Author=tizi
		Query(elastic.NewTermQuery("Author", "tizi")).
                // 通过脚本更新内容,将Title字段改为1111111
		Script(elastic.NewScript( "ctx._source['Title']='1111111'")).
                // 如果文档版本冲突继续执行
		ProceedOnVersionConflict(). 
		Do(ctx)

提示: 复杂查询条件,请参考go es查询用法

删除文档

// 根据id删除一条数据
_, err := client.Delete().
		Index("blogs").
		Id("1").  // 文档id
		Do(ctx)
if err != nil {
	// Handle error
	panic(err)
}

根据条件删除文档

_, _ = client.DeleteByQuery("blogs"). // 设置索引名
	    // 设置查询条件为: Author = tizi
		Query(elastic.NewTermQuery("Author", "tizi")).
		// 文档冲突也继续删除
		ProceedOnVersionConflict().
		Do(ctx)

提示: 复杂查询条件,请参考go es查询用法