GO学习之 搜索引擎(ElasticSearch)

GO系列

1、GO学习之Hello World
2、GO学习之入门语法
3、GO学习之切片操作
4、GO学习之 Map 操作
5、GO学习之 结构体 操作
6、GO学习之 通道(Channel)
7、GO学习之 多线程(goroutine)
8、GO学习之 函数(Function)
9、GO学习之 接口(Interface)
10、GO学习之 网络通信(Net/Http)
11、GO学习之 微框架(Gin)
12、GO学习之 数据库(mysql)
13、GO学习之 数据库(Redis)
14、GO学习之 搜索引擎(ElasticSearch)
15、GO学习之 消息队列(Kafka)
16、GO学习之 远程过程调用(RPC)
17、GO学习之 goroutine的调度原理
18、GO学习之 通道(nil Channel妙用)
19、GO学习之 同步操作sync包
20、GO学习之 互斥锁、读写锁该如何取舍
21、GO学习之 条件变量 sync.Cond
22、GO学习之 单例模式 sync.Once
23、GO 面试题总结一【面试官这样问】
24、GO 面试题进阶篇【面试官这样问】

前言

按照公司目前的任务,go 学习是必经之路了,虽然行业卷,不过技多不压身,依旧努力!!!
一个网站或者一个平台好不了模糊检索,传统的SQL检索无法满足,而且效率也地下,所以目前大多数项目中搜索都用的是搜索引擎(ElasticSearch较多,简称 ES),那什么是 ES呢?请移步 ElasticSearch学习随笔之基础介绍 等系列文章,项目中客户端使用也是 JAVA 的实现的。
此篇就来聊聊如何用 GoES 进行检索等各种常用操作。

一、ElasticSearch 简介

ElasticSearch 是一个开源的分布式搜索和分析引擎,基于 Apache Lucene 开发的。被广泛用于实时检索、数据分析和数据可视化等领域,具有高性能、可扩展和强大的全文检索能力。

  1. 分布式和实时性: ES 架构允许数据在集群中分布,实现水平扩展和高吞吐量。能够在毫秒级别内实时对大量数据进行检索。
  2. 全文检索: 强大的全文搜索功能,支持多种查询、模糊检索等,能够高效地匹配和检索文本数据。
  3. 多数据支持: ES 不仅支持结构化数据,还可以存储和处理非结构化或半结构化的文本数据、地理空间数据等。
  4. RESTful API: ES提供简单易用的 RESUful API,允许通过HTTP请求进行数据操作和查询。
  5. 索引和分片: 数据存储以索引为单位存储,每个索引可以被分成多个分片,每个分片分布在不同的节点上。
  6. 查询和聚合: ES 提供了强大的查询和聚合功能,可以进行高级搜索、过滤、分组、计算等操作。
  7. 数据可视化: 通过 kibana(ES 和 Logstash配套工具) 可以进行数据进行可视化、仪表盘和数据报表展示。
  8. 近实时复制和更新: ES支持近实时将数据复制到其他节点或集群,近实时更新数据,更新后很快就能检索到。
  9. 插件和扩展性: 丰富的插件,通过插件扩展功能,满足不同的需求。
  10. 安全和权限控制: 提供了 访问控制、认证和授权等功能,保障数据安全性。

二、基本操作

在进行 ES 操作之前,我们首先要将操作ES的包拉取:

go get github.com/olivere/elastic/v7

2.0 创建ES链接

下面的示例中,我们创建了一个 ES 链接,用来操作ES,在 common 包中,并且 函数名(GetESClient())是大写的,表示外部包可访问。

package common

import (
	"fmt"
	"log"

	"github.com/olivere/elastic/v7"
)

func GetESClient() *elastic.Client {
	// 建立 ElasticSearch 连接
	client, err := elastic.NewClient(elastic.SetURL("http://192.168.1.8:9200"))
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("ES链接创建成功!")
	return client
}

2.1 增

下面示例是利用 Bulk批量新增操作,获取到 ES 的链接后,通过 esClient.Bulk()创建批量操作 Bulk,然后再通过 Add(doc)把文档添加到批量操作里面,最后 Do() 执行操作。

package main

import (
	"context"
	"fmt"
	"log"

	"github.com/olivere/elastic/v7"
	"gotest.com/test/src/common"
)

// 创建结构体
type Content struct {
	Product        string   `json:"product"`
	Color          string   `json:"color"`
	Release_date   string   `json:"release_date"`
	Price          float32  `json:"price"`
	Product_agency []string `json:"product_agency"`
	Types          string   `json:"types"`
	Title          string   `json:"title"`
	Brand          string   `json:"brand"`
	Desc           string   `json:"desc"`
}

func main() {
	// 建立 ElasticSearch 连接
	esClient := common.GetESClient()

	// 创建文档
	contents := []Content{
		{
			Product: "Xbox Series 10", Color: "black", Release_date: "2023-08-27", Price: 500.25, Product_agency: []string{"玩游戏", "看电影"}, Types: "gaming console",
			Title: "微软 Xbox Y", Brand: "Microsoft", Desc: "这是一款拥有强大性能和兼容性的游戏机, 能看电影,红色的",
		},
		{
			Product: "Xbox Series 10", Color: "green", Release_date: "2023-08-27", Price: 500.25, Product_agency: []string{"玩游戏", "看电影"}, Types: "gaming console",
			Title: "微软 Xbox Y", Brand: "Microsoft", Desc: "这是一款拥有强大性能和兼容性的游戏机, 能看电影,绿色的",
		},
	}

	// 批量操作
	bulkRequest := esClient.Bulk()

	// 批量添加文档
	for _, content := range contents {

		doc := elastic.NewBulkCreateRequest().Index("electronics").UseEasyJSON(true).Doc(&content)
		bulkRequest.Add(doc)
	}
	// 执行批量添加操作
	result, err := bulkRequest.Do(context.Background())
	if err != nil {
		log.Fatal(err)
	}

	fmt.Printf("成功添加 %v 个文档", len(result.Succeeded()))
}

2.2 删

此示例通过 ID 删除文档。

package main

import (
	"context"
	"fmt"
	"log"

	"gotest.com/test/src/common"
)

func main() {
	// 建立 ElasticSearch 连接
	esClient := common.GetESClient()
	_, err := esClient.Delete().Index("electronics").Id("n72VNooB2xU2Yn1oN-Bc").Do(context.Background())
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("删除成功!")
}

2.3 改

此案例按照 ID 修改。

package main

import (
	"context"
	"fmt"
	"log"

	"gotest.com/test/src/common"
)

func main() {
	// 建立 ElasticSearch 连接
	esClient := common.GetESClient()

	_, err := esClient.Update().Index("electronics").Id("nr2VNooB2xU2Yn1oN-Bc").Doc(map[string]interface{}{"title": "微软 Xbox Z"}).Do(context.Background())
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("文档已更新!")
}

2.4 检索

2.4.1 分页获取全部数据

package main

import (
	"context"
	"encoding/json"
	"fmt"
	"log"

	"github.com/olivere/elastic/v7"
	"gotest.com/test/src/common"
)

func main() {
	// 建立 ElasticSearch 连接
	esClient := common.GetESClient()

	// match all 数据匹配
	query := elastic.NewMatchAllQuery()
	// 检索 从 0 到 10 条数据
	result, err := esClient.Search().Index("electronics").Query(query).From(0).Size(10).Do(context.Background())
	if err != nil {
		log.Fatal(err)
	}

	// 定一个 结构体,结构化数据
	type product struct {
		Product string
		Color   string
		Title   string
	}

	// 处理数据结果
	fmt.Printf("总条数:%+v\n", result.Hits.TotalHits.Value)
	for index, hit := range result.Hits.Hits {
		p := &product{}
		// hit.Source 获取到的数据,经过 json 反序列化转换成 product 结构体
		pErr := json.Unmarshal(hit.Source, p)
		if pErr != nil {
			log.Fatal(pErr)
		}
		fmt.Println(index, p)
	}
}

运行结果:

PS D:\workspaceGo\src\elasticSearch> go run .\query.go
ES链接创建成功!
总条数:22
0 &{Galaxy S21 white 三星 Galaxy S21}
1 &{Galaxy S21 white 三星 Galaxy S21}
2 &{Canon EOS 5D Mark IV black 佳能 EOS 5D Mark IV}
3 &{Sony A7 III black 索尼 A7 III}
4 &{GoPro HERO10 Black black GoPro HERO10 Black}
5 &{Apple Watch Series 7 space gray 苹果 Watch Series 7}
6 &{Samsung Galaxy Watch 4 black 三星 Galaxy Watch 4}
7 &{Nintendo Switch OLED red/blue 任天堂 Switch OLED}
8 &{PlayStation 5 white 索尼 PlayStation 5}
9 &{Xbox Series X black 微软 Xbox Series X}

2.4.2 各种检索

2.4.2.1 match 检索
query := elastic.NewMatchQuery("brand", "Apple")
2.4.2.2 prefix 前缀匹配
query := elastic.NewMatchBoolPrefixQuery("title", "三")
2.4.2.3 phrase 前缀匹配
query := elastic.NewMatchPhrasePrefixQuery("desc", "时尚与智能")
2.4.2.4 phrase 短语匹配
query := elastic.NewMatchPhraseQuery("desc", "时尚与智能")
2.4.2.5 match 多字段匹配
query := elastic.NewMultiMatchQuery("苹果", "title", "brand", "product")
2.4.2.6 term 精确匹配
query := elastic.NewTermQuery("type", "mobile")
2.4.2.7 terms 多值精确匹配
query := elastic.NewTermsQuery("color", "white", "black")
2.4.2.8 fuzzy 模糊匹配
	// Fuzziness 检索模糊距离
	query := elastic.NewFuzzyQuery("desc", "手机").Fuzziness(5)
2.4.2.9 bool 组合匹配
query := elastic.NewBoolQuery().Should(elastic.NewMatchQuery("title", "手机"), elastic.NewTermQuery("type", "mobile"))
2.4.2.10 dis max 最佳字段匹配
query := elastic.NewDisMaxQuery().Query(elastic.NewMatchQuery("title", "苹果"), elastic.NewMatchQuery("desc", "苹果"))

2.4.3 聚合操作

package main

import (
	"context"
	"fmt"
	"log"

	"github.com/olivere/elastic/v7"
	"gotest.com/test/src/common"
)
func main() {
	// 建立 ElasticSearch 连接
	esClient := common.GetESClient()
	// 构建统计
	agg := elastic.NewTermsAggregation().Field("color.keyword")
	// 执行搜索和聚合操作
	result, err := esClient.Search().Index("electronics").Aggregation("by_color", agg).Do(context.Background())
	if err != nil {
		log.Fatal(err)
	}
	// 处理聚合结果
	aggResult, found := result.Aggregations.Terms("by_color")
	if found {
		for _, bucket := range aggResult.Buckets {
			fmt.Printf("color: %v, count: %v \n", bucket.Key, bucket.DocCount)
		}
	}
}

运行结果:

PS D:\workspaceGo\src\elasticSearch> go run .\aggregation.go
ES链接创建成功!
color: black, count: 9 
color: white, count: 6
color: silver, count: 3
color: red/blue, count: 1
color: space gray, count: 1
color: stainless steel, count: 1

三、第三方库

  1. github.com/olivere/elastic/v7
  • 是 ElasticSearch 官方维护的的 Go 客户端。
  • 提供了丰富的的功能,包括 索引、查询、聚合、分页等。
  • 支持链接池、超时控制、请求重试等特性。
  1. github.com/elastic/go-elasticsearch/v7
  • 是 ElasticSearch 官方维护的另一个客户端库,提供了更低级别的 API,可以更精细地控制请求和响应。

四、总结

优点:

  1. 高性能: Go语言本身具有更出色的性能,适合于处理高并发和大规模数据。使得 Go 操作 ElasticSearch 可以实现快速的数据索引、查询和分析。
  2. 并发处理: Go 语言支持轻量级协程(goroutine),可以更方便地实现并发和并行处理,从而提高 ElasticSearch 操作的效率。
  3. 第三方库: Go 社区中,多个优秀的第三方用于操作 ElasticSearch,方便开发。

缺点:

  1. 生态相对较小: 相对于其他一些编译语言,Go 语言的生态系统相对小。
  2. 少量的高级功能: ElasticSearch 的高级功能可能需要更丰富的配置和处理。

总的来说,使用 Go 语言操作 ElasticSearch 具有高性能、并发性和易维护性等优势,适用于需要快速、高效处理大量数据的场景。不过,也需要根据项目需求和团队技术栈的考量来决定是否选择 Go 语言来操作 ElasticSearch。


现阶段还是对 Go 语言的学习阶段,想必有一些地方考虑的不全面,本文示例全部是亲自手敲代码并且执行通过。
如有问题,还请指教。
评论去告诉我哦!!!一起学习一起进步!!!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值