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)

文章目录

  • GO系列
  • 前言
  • [一、ElasticSearch 简介](#一、ElasticSearch 简介)
  • 二、基本操作
    • [2.0 创建ES链接](#2.0 创建ES链接)
    • [2.1 增](#2.1 增)
    • [2.2 删](#2.2 删)
    • [2.3 改](#2.3 改)
    • [2.4 检索](#2.4 检索)
      • [2.4.1 分页获取全部数据](#2.4.1 分页获取全部数据)
      • [2.4.2 各种检索](#2.4.2 各种检索)
        • [2.4.2.1 match 检索](#2.4.2.1 match 检索)
        • [2.4.2.2 prefix 前缀匹配](#2.4.2.2 prefix 前缀匹配)
        • [2.4.2.3 phrase 前缀匹配](#2.4.2.3 phrase 前缀匹配)
        • [2.4.2.4 phrase 短语匹配](#2.4.2.4 phrase 短语匹配)
        • [2.4.2.5 match 多字段匹配](#2.4.2.5 match 多字段匹配)
        • [2.4.2.6 term 精确匹配](#2.4.2.6 term 精确匹配)
        • [2.4.2.7 terms 多值精确匹配](#2.4.2.7 terms 多值精确匹配)
        • [2.4.2.8 fuzzy 模糊匹配](#2.4.2.8 fuzzy 模糊匹配)
        • [2.4.2.9 bool 组合匹配](#2.4.2.9 bool 组合匹配)
        • [2.4.2.10 dis max 最佳字段匹配](#2.4.2.10 dis max 最佳字段匹配)
    • [2.4.3 聚合操作](#2.4.3 聚合操作)
  • 三、第三方库
  • 四、总结

前言

按照公司目前的任务,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 复制代码
go get github.com/olivere/elastic/v7

2.0 创建ES链接

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

go 复制代码
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() 执行操作。

go 复制代码
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 删除文档。

go 复制代码
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 修改。

go 复制代码
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 分页获取全部数据

go 复制代码
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)
	}
}

运行结果:

bash 复制代码
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 检索

go 复制代码
query := elastic.NewMatchQuery("brand", "Apple")

2.4.2.2 prefix 前缀匹配

go 复制代码
query := elastic.NewMatchBoolPrefixQuery("title", "三")

2.4.2.3 phrase 前缀匹配

go 复制代码
query := elastic.NewMatchPhrasePrefixQuery("desc", "时尚与智能")

2.4.2.4 phrase 短语匹配

go 复制代码
query := elastic.NewMatchPhraseQuery("desc", "时尚与智能")

2.4.2.5 match 多字段匹配

go 复制代码
query := elastic.NewMultiMatchQuery("苹果", "title", "brand", "product")

2.4.2.6 term 精确匹配

go 复制代码
query := elastic.NewTermQuery("type", "mobile")

2.4.2.7 terms 多值精确匹配

go 复制代码
query := elastic.NewTermsQuery("color", "white", "black")

2.4.2.8 fuzzy 模糊匹配

go 复制代码
	// Fuzziness 检索模糊距离
	query := elastic.NewFuzzyQuery("desc", "手机").Fuzziness(5)

2.4.2.9 bool 组合匹配

go 复制代码
query := elastic.NewBoolQuery().Should(elastic.NewMatchQuery("title", "手机"), elastic.NewTermQuery("type", "mobile"))

2.4.2.10 dis max 最佳字段匹配

go 复制代码
query := elastic.NewDisMaxQuery().Query(elastic.NewMatchQuery("title", "苹果"), elastic.NewMatchQuery("desc", "苹果"))

2.4.3 聚合操作

go 复制代码
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)
		}
	}
}

运行结果:

bash 复制代码
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 语言的学习阶段,想必有一些地方考虑的不全面,本文示例全部是亲自手敲代码并且执行通过。
如有问题,还请指教。

评论去告诉我哦!!!一起学习一起进步!!!

相关推荐
花酒锄作田3 天前
Gin 框架中的规范响应格式设计与实现
golang·gin
qwfys2004 天前
How to install golang 1.26.0 to Ubuntu 24.04
ubuntu·golang·install
嗝屁小孩纸4 天前
ES索引重建(零工具纯脚本执行)
大数据·elasticsearch·搜索引擎
Elastic 中国社区官方博客4 天前
使用 Jina Embeddings v5 和 Elasticsearch 构建“与你的网站数据聊天”的 agent
大数据·人工智能·elasticsearch·搜索引擎·容器·全文检索·jina
codeejun4 天前
每日一Go-25、Go语言进阶:深入并发模式1
开发语言·后端·golang
石牌桥网管4 天前
Go 泛型(Generics)
服务器·开发语言·golang
小二·4 天前
Go 语言系统编程与云原生开发实战(第21篇)
开发语言·云原生·golang
小二·4 天前
Go 语言系统编程与云原生开发实战(第20篇)
开发语言·云原生·golang
女王大人万岁4 天前
Golang实战Eclipse Paho MQTT库:MQTT通信全解析
服务器·开发语言·后端·golang
codeejun4 天前
每日一Go-24、Go语言实战-综合项目:规划与搭建
开发语言·后端·golang