1.Golang操作 ElasticSearchプラグイン導入
ElasticSearch を動作させるための一般的な Golang プラグインには主に次の 2 つがあります。
サードパーティ製プラグイン: github.com/olivere/elastic
公式 Web サイトのプラグ イン github.com/elastic/go-elasticsearch
このうち、 Elastic はより 包括的です。 go-elasticsearch ドキュメント、開始量もさらに多く、このセクションでは elastic について説明します
2. Elasticプラグインの使用
サードパーティライブラリ https://github.com/olivere/elastic を使用して ES を接続し、操作します
注:
ES と同じバージョンのクライアントをダウンロードします。たとえば、ここで使用する ES は 7.x バージョンです。
ダウンロードした github.com/olivere/elastic/v7として対応する必要があります。
import (
... "github.com/olivere/elastic/v7"
)
公式サンプルコードリファレンス: https://godoc.org/github.com/olivere/elastic
3.GinのElasticプラグインを使用してデータの追加、削除、変更、クエリを実現します
新しいモデルの作成/esCore.go
Elastic プラグインを導入し、最初にesCore.go に github.com/olivere/elastic/v7 をインポートしてから、 main.go ファイルでコマンド go mod tiny を実行します。 注: Elastic バージョンは ES バージョンに対応する必要があります。
package models
//es插件使用
import (
"fmt"
"github.com/olivere/elastic/v7"
)
var EsClient *elastic.Client
func init() {
//注意IP和端口
EsClient, err = elastic.NewClient(elastic.SetURL("http://127.0.0.1:9200"))
if err != nil {
fmt.Println(err)
}
}
ルーティング
ElasticSearch 関連のルートを router/frontendRouters.go に追加します。
//设置es索引以及配置
defaultRouters.GET("/search", frontend.SearchController{}.Index)
//获取一条es数据
defaultRouters.GET("/search/getOne", frontend.SearchController{}.GetOne)
//增加数据到es中
defaultRouters.GET("/search/addGoods", frontend.SearchController{}.AddGoods)
//更新es中对应的数据
defaultRouters.GET("/search/updateGoods", frontend.SearchController{}.UpdateGoods)
//删除es中的数据
defaultRouters.GET("/search/deleteGoods", frontend.SearchController{}.DeleteGoods)
//模糊查询es数据
defaultRouters.GET("/search/query", frontend.SearchController{}.Query)
//条件筛选es查询
defaultRouters.GET("/search/filterQuery", frontend.SearchController{}.FilterQuery)
//分页查询es数据
defaultRouters.GET("/search/pagingQuery", frontend.SearchController{}.PagingQuery)
コントローラー関連のコード
関連メソッド:
es インデックスと構成の設定、es データの一部の取得、es へのデータの追加、es 内の対応するデータの更新、es 内のデータの削除、ファジー クエリ es データ、条件付きフィルター es クエリ、ページ クエリ es データ
package frontend
//Elasticsearch 控制器
import (
"context"
"encoding/json"
"fmt"
"goshop/models"
"reflect"
"strconv"
"github.com/gin-gonic/gin"
"github.com/olivere/elastic/v7"
)
type SearchController struct {
BaseController
}
//初始化的时候判断索引goods是否存在,创建索引配置映射
func (con SearchController) Index(c *gin.Context) {
exists, err := models.EsClient.IndexExists("goods").Do(context.Background())
if err != nil {
// Handle error
fmt.Println(err)
}
print(exists)
if !exists {
// 配置映射
mapping := `
{
"settings": { //设置
"number_of_shards": 1, //分区数配置
"number_of_replicas": 0 //副本数配置
},
"mappings": { //映射
"properties": {
"Content": { //映射属性
"type": "text", //类型
"analyzer": "ik_max_word", // 检测粒度
"search_analyzer": "ik_max_word" //搜索粒度
},
"Title": {
"type": "text",
"analyzer": "ik_max_word",
"search_analyzer": "ik_max_word"
}
}
}
}
`
//注意:增加的写法-创建索引配置映射
_, err := models.EsClient.CreateIndex("goods").Body(mapping).Do(context.Background())
if err != nil {
// Handle error
fmt.Println(err)
}
}
c.String(200, "创建索引配置映射成功")
}
//增加商品数据到es
func (con SearchController) AddGoods(c *gin.Context) {
//获取数据库中的商品数据
goods := []models.Goods{}
models.DB.Find(&goods)
//循环商品,把每个商品存入es
for i := 0; i < len(goods); i++ {
_, err := models.EsClient.Index().
Index("goods"). //设置索引
Type("_doc"). //设置类型
Id(strconv.Itoa(goods[i].Id)). //设置id
BodyJson(goods[i]). //设置商品数据(结构体格式)
Do(context.Background())
if err != nil {
// Handle error
fmt.Println(err)
}
}
c.String(200, "AddGoods success")
}
//更新数据
func (con SearchController) UpdateGoods(c *gin.Context) {
goods := []models.Goods{}
models.DB.Find(&goods)
goods[0].Title = "我是修改后的数据"
goods[0].GoodsContent = "我是修改后的数据GoodsContent"
_, err := models.EsClient.Update().
Index("goods").
Type("_doc").
Id("19"). //要修改的数据id
Doc(goods[0]). //要修改的数据结构体
Do(context.Background())
if err != nil {
// Handle error
fmt.Println(err)
}
c.String(200, "修改数据 success")
}
//删除
func (con SearchController) DeleteGoods(c *gin.Context) {
_, err := models.EsClient.Delete().
Index("goods").
Type("_doc").
Id("19").
Do(context.Background())
if err != nil {
// Handle error
fmt.Println(err)
}
c.String(200, "删除成功 success")
}
//查询一条数据
func (con SearchController) GetOne(c *gin.Context) {
//defer 操作:捕获panic数据
defer func() {
if r := recover(); r != nil {
fmt.Println("Recovered in f", r)
c.String(200, "GetOne Error")
}
}()
result, err := models.EsClient.Get().
Index("goods").
Type("_doc").
Id("19").
Do(context.Background())
if err != nil { //判断数据是否存在,不存在则panic
// Some other kind of error
panic(err)
}
goods := models.Goods{} //实例化一个商品结构体
json.Unmarshal(result.Source, &goods) //把result结果解析到goods中
c.JSON(200, gin.H{
"goods": goods,
})
}
//模糊查询数据
func (con SearchController) Query(c *gin.Context) {
defer func() {
if r := recover(); r != nil {
fmt.Println("Recovered in f", r)
c.String(200, "Query Error")
}
}()
//模糊查询操作
query := elastic.NewMatchQuery("Title", "手机") //Title中包含 手机 的数据
searchResult, err := models.EsClient.Search().
Index("goods"). // search in index "goods"
Query(query). // specify the query
Do(context.Background()) // execute
if err != nil {
// Handle error
panic(err)
}
goods := models.Goods{}
c.JSON(200, gin.H{
"searchResult": searchResult.Each(reflect.TypeOf(goods)), //查询的结果:reflect.TypeOf(goods)类型断言,可以判断是否商品结构体
})
}
//分页查询
func (con SearchController) PagingQuery(c *gin.Context) {
defer func() {
if r := recover(); r != nil {
fmt.Println("Recovered in f", r)
c.String(200, "Query Error")
}
}()
page, _ := strconv.Atoi(c.Query("page")) //获取当前页码数
if page == 0 {
page = 1
}
pageSize := 2
query := elastic.NewMatchQuery("Title", "手机")
searchResult, err := models.EsClient.Search().
Index("goods"). // search in index "goods"
Query(query). // specify the query
Sort("Id", true). // true 表示升序 false 降序
From((page - 1) * pageSize).Size(pageSize). // 分页查询
Do(context.Background()) // execute
if err != nil {
// Handle error
panic(err)
}
goods := models.Goods{}
c.JSON(200, gin.H{
"searchResult": searchResult.Each(reflect.TypeOf(goods)),
})
}
//条件筛选查询
func (con SearchController) FilterQuery(c *gin.Context) {
defer func() {
if r := recover(); r != nil {
fmt.Println("Recovered in f", r)
c.String(200, "Query Error")
}
}()
//筛选
boolQ := elastic.NewBoolQuery()
boolQ.Must(elastic.NewMatchQuery("Title", "小米"))
boolQ.Filter(elastic.NewRangeQuery("Id").Gt(19)) //Id 大于19
boolQ.Filter(elastic.NewRangeQuery("Id").Lt(42)) //Id 小于42
searchResult, err := models.EsClient.Search().
Index("goods").
Type("_doc").
Sort("Id", true).
Query(boolQ).
Do(context.Background())
if err != nil {
fmt.Println(err)
}
goodsList := []models.Goods{}
var goods models.Goods
for _, item := range searchResult.Each(reflect.TypeOf(goods)) { //循环搜索结果,并把结果类型断言goods,如果结果类型是商品数据类型,则循环处理
t := item.(models.Goods)
fmt.Printf("Id:%v 标题:%v\n", t.Id, t.Title)
goodsList = append(goodsList, t)
}
c.JSON(200, gin.H{
"goodsList": goodsList,
})
}
[前節] [golang gin フレームワーク] 37. 全文検索エンジン ElasticSearch の利用
[次のセクション] [golang gin フレームワーク] 39. Gin Mall プロジェクト - マイクロサービス実践におけるマイクロサービス アーキテクチャ