当前位置: 首页 > news >正文

Golang操作ES

文章目录

  • Golang操作ES快速入门
    • 创建项目
    • 安装包
    • 连接到ES
    • 运行结果
  • Golang操作ES索引
    • es API
    • 创建索引
    • 查询索引
    • 删除索引
  • Golang操作ES文档
    • 插入文档
      • 步骤一:导包
      • 步骤二:为文档字段创捷结构体
      • 步骤三:将结构体转换为JSON字符串
      • 步骤四:创建 Elasticsearch Golang 客户端实例
      • 步骤五:实例化 Elasticsearch 客户端配置和 Golang 客户端实例
      • 步骤六:检查与 Elasticsearch 的连接
      • 步骤七:创建 Elasticsearch 结构文档并将其放入数组
      • 步骤八:迭代文档数组并调用 Golang 客户端的 `IndexRequest()` 方法
      • 步骤九:检查 IndexRequest() 方法调用是否返回任何错误
      • 代码总结
      • 运行结果
      • postman中查看插入的数据
    • 查询文档
    • 删除文档
  • Gin集成ES
    • 创建一个项目gin_es
    • 创建两个页面
    • 处理集成逻辑
    • 测试


Golang操作ES快速入门

创建项目

创建一个项目demo,初始化项目go mod init demo

安装包

go get github.com/elastic/go-elasticsearch/v7

连接到ES

package main

import (
	"log"

	"github.com/elastic/go-elasticsearch/v7"
)

func main() {
	es, err := elasticsearch.NewDefaultClient()// 连接到es服务器
	if err != nil {
		panic(err)
	}
	log.Println(elasticsearch.Version)
	log.Println(es.Info())
}

运行结果

[Running] go run "e:\golang开发学习\es\main.go"
2022/09/24 13:16:22 7.17.1
2022/09/24 13:16:22 [200 OK] {
  "name" : "MORAX",
  "cluster_name" : "elasticsearch",
  "cluster_uuid" : "HoU0Tw3WTiSMD2GRzezqnw",
  "version" : {
    "number" : "7.8.1",
    "build_flavor" : "default",
    "build_type" : "zip",
    "build_hash" : "b5ca9c58fb664ca8bf9e4057fc229b3396bf3a89",
    "build_date" : "2020-07-21T16:40:44.668009Z",
    "build_snapshot" : false,
    "lucene_version" : "8.5.1",
    "minimum_wire_compatibility_version" : "6.8.0",
    "minimum_index_compatibility_version" : "6.0.0-beta1"
  },
  "tagline" : "You Know, for Search"
}
 <nil>

[Done] exited with code=0 in 2.516 seconds

Golang操作ES索引

es API

我们获得es客户端实例后,通过客户端实例可以获得es api,内容如下:

package esapi

// API contains the Elasticsearch APIs
//
type API struct {
	Cat         *Cat
	Cluster     *Cluster
	Indices     *Indices
	Ingest      *Ingest
	Nodes       *Nodes
	Remote      *Remote
	Snapshot    *Snapshot
	Tasks       *Tasks
	AsyncSearch *AsyncSearch
	CCR         *CCR
	ILM         *ILM
	License     *License
	Migration   *Migration
	ML          *ML
	Monitoring  *Monitoring
	Rollup      *Rollup
	Security    *Security
	SQL         *SQL
	SSL         *SSL
	Watcher     *Watcher
	XPack       *XPack

	AutoscalingDeleteAutoscalingPolicy            AutoscalingDeleteAutoscalingPolicy
	AutoscalingGetAutoscalingCapacity             AutoscalingGetAutoscalingCapacity
	AutoscalingGetAutoscalingDecision             AutoscalingGetAutoscalingDecision
	AutoscalingGetAutoscalingPolicy               AutoscalingGetAutoscalingPolicy
	AutoscalingPutAutoscalingPolicy               AutoscalingPutAutoscalingPolicy
	Bulk                                          Bulk
	ClearScroll                                   ClearScroll
	ClosePointInTime                              ClosePointInTime
	Count                                         Count
	Create                                        Create
	DanglingIndicesDeleteDanglingIndex            DanglingIndicesDeleteDanglingIndex
	DanglingIndicesImportDanglingIndex            DanglingIndicesImportDanglingIndex
	DanglingIndicesListDanglingIndices            DanglingIndicesListDanglingIndices
	DataFrameTransformDeprecatedDeleteTransform   DataFrameTransformDeprecatedDeleteTransform
	DataFrameTransformDeprecatedGetTransform      DataFrameTransformDeprecatedGetTransform
	DataFrameTransformDeprecatedGetTransformStats DataFrameTransformDeprecatedGetTransformStats
	DataFrameTransformDeprecatedPreviewTransform  DataFrameTransformDeprecatedPreviewTransform
	DataFrameTransformDeprecatedPutTransform      DataFrameTransformDeprecatedPutTransform
	DataFrameTransformDeprecatedStartTransform    DataFrameTransformDeprecatedStartTransform
	DataFrameTransformDeprecatedStopTransform     DataFrameTransformDeprecatedStopTransform
	DataFrameTransformDeprecatedUpdateTransform   DataFrameTransformDeprecatedUpdateTransform
	DeleteByQuery                                 DeleteByQuery
	DeleteByQueryRethrottle                       DeleteByQueryRethrottle
	Delete                                        Delete
	DeleteScript                                  DeleteScript
	EnrichDeletePolicy                            EnrichDeletePolicy
	EnrichExecutePolicy                           EnrichExecutePolicy
	EnrichGetPolicy                               EnrichGetPolicy
	EnrichPutPolicy                               EnrichPutPolicy
	EnrichStats                                   EnrichStats
	EqlDelete                                     EqlDelete
	EqlGet                                        EqlGet
	EqlGetStatus                                  EqlGetStatus
	EqlSearch                                     EqlSearch
	Exists                                        Exists
	ExistsSource                                  ExistsSource
	Explain                                       Explain
	FeaturesGetFeatures                           FeaturesGetFeatures
	FeaturesResetFeatures                         FeaturesResetFeatures
	FieldCaps                                     FieldCaps
	FleetGlobalCheckpoints                        FleetGlobalCheckpoints
	FleetMsearch                                  FleetMsearch
	FleetSearch                                   FleetSearch
	Get                                           Get
	GetScriptContext                              GetScriptContext
	GetScriptLanguages                            GetScriptLanguages
	GetScript                                     GetScript
	GetSource                                     GetSource
	GraphExplore                                  GraphExplore
	Index                                         Index
	Info                                          Info
	LogstashDeletePipeline                        LogstashDeletePipeline
	LogstashGetPipeline                           LogstashGetPipeline
	LogstashPutPipeline                           LogstashPutPipeline
	Mget                                          Mget
	Msearch                                       Msearch
	MsearchTemplate                               MsearchTemplate
	Mtermvectors                                  Mtermvectors
	OpenPointInTime                               OpenPointInTime
	Ping                                          Ping
	PutScript                                     PutScript
	RankEval                                      RankEval
	Reindex                                       Reindex
	ReindexRethrottle                             ReindexRethrottle
	RenderSearchTemplate                          RenderSearchTemplate
	ScriptsPainlessExecute                        ScriptsPainlessExecute
	Scroll                                        Scroll
	SearchMvt                                     SearchMvt
	Search                                        Search
	SearchShards                                  SearchShards
	SearchTemplate                                SearchTemplate
	SearchableSnapshotsCacheStats                 SearchableSnapshotsCacheStats
	SearchableSnapshotsClearCache                 SearchableSnapshotsClearCache
	SearchableSnapshotsMount                      SearchableSnapshotsMount
	SearchableSnapshotsRepositoryStats            SearchableSnapshotsRepositoryStats
	SearchableSnapshotsStats                      SearchableSnapshotsStats
	ShutdownDeleteNode                            ShutdownDeleteNode
	ShutdownGetNode                               ShutdownGetNode
	ShutdownPutNode                               ShutdownPutNode
	SlmDeleteLifecycle                            SlmDeleteLifecycle
	SlmExecuteLifecycle                           SlmExecuteLifecycle
	SlmExecuteRetention                           SlmExecuteRetention
	SlmGetLifecycle                               SlmGetLifecycle
	SlmGetStats                                   SlmGetStats
	SlmGetStatus                                  SlmGetStatus
	SlmPutLifecycle                               SlmPutLifecycle
	SlmStart                                      SlmStart
	SlmStop                                       SlmStop
	TermsEnum                                     TermsEnum
	Termvectors                                   Termvectors
	TextStructureFindStructure                    TextStructureFindStructure
	TransformDeleteTransform                      TransformDeleteTransform
	TransformGetTransform                         TransformGetTransform
	TransformGetTransformStats                    TransformGetTransformStats
	TransformPreviewTransform                     TransformPreviewTransform
	TransformPutTransform                         TransformPutTransform
	TransformStartTransform                       TransformStartTransform
	TransformStopTransform                        TransformStopTransform
	TransformUpdateTransform                      TransformUpdateTransform
	TransformUpgradeTransforms                    TransformUpgradeTransforms
	UpdateByQuery                                 UpdateByQuery
	UpdateByQueryRethrottle                       UpdateByQueryRethrottle
	Update                                        Update
}

API结构体里面包含了Indices,内容如下:

// Indices contains the Indices APIs
type Indices struct {
	AddBlock              IndicesAddBlock
	Analyze               IndicesAnalyze
	ClearCache            IndicesClearCache
	Clone                 IndicesClone
	Close                 IndicesClose
	CreateDataStream      IndicesCreateDataStream
	Create                IndicesCreate
	DataStreamsStats      IndicesDataStreamsStats
	DeleteAlias           IndicesDeleteAlias
	DeleteDataStream      IndicesDeleteDataStream
	DeleteIndexTemplate   IndicesDeleteIndexTemplate
	Delete                IndicesDelete
	DeleteTemplate        IndicesDeleteTemplate
	DiskUsage             IndicesDiskUsage
	ExistsAlias           IndicesExistsAlias
	ExistsDocumentType    IndicesExistsDocumentType
	ExistsIndexTemplate   IndicesExistsIndexTemplate
	Exists                IndicesExists
	ExistsTemplate        IndicesExistsTemplate
	FieldUsageStats       IndicesFieldUsageStats
	Flush                 IndicesFlush
	FlushSynced           IndicesFlushSynced
	Forcemerge            IndicesForcemerge
	Freeze                IndicesFreeze
	GetAlias              IndicesGetAlias
	GetDataStream         IndicesGetDataStream
	GetFieldMapping       IndicesGetFieldMapping
	GetIndexTemplate      IndicesGetIndexTemplate
	GetMapping            IndicesGetMapping
	Get                   IndicesGet
	GetSettings           IndicesGetSettings
	GetTemplate           IndicesGetTemplate
	GetUpgrade            IndicesGetUpgrade
	MigrateToDataStream   IndicesMigrateToDataStream
	ModifyDataStream      IndicesModifyDataStream
	Open                  IndicesOpen
	PromoteDataStream     IndicesPromoteDataStream
	PutAlias              IndicesPutAlias
	PutIndexTemplate      IndicesPutIndexTemplate
	PutMapping            IndicesPutMapping
	PutSettings           IndicesPutSettings
	PutTemplate           IndicesPutTemplate
	Recovery              IndicesRecovery
	Refresh               IndicesRefresh
	ReloadSearchAnalyzers IndicesReloadSearchAnalyzers
	ResolveIndex          IndicesResolveIndex
	Rollover              IndicesRollover
	Segments              IndicesSegments
	ShardStores           IndicesShardStores
	Shrink                IndicesShrink
	SimulateIndexTemplate IndicesSimulateIndexTemplate
	SimulateTemplate      IndicesSimulateTemplate
	Split                 IndicesSplit
	Stats                 IndicesStats
	Unfreeze              IndicesUnfreeze
	UpdateAliases         IndicesUpdateAliases
	Upgrade               IndicesUpgrade
	ValidateQuery         IndicesValidateQuery
}

该结构体包含了操作索引的一些方法,例如:创建索引Create、查询索引Get、删除索引Delete

创建索引

创建索引函数如下:

type IndicesCreate func(index string, o ...func(*IndicesCreateRequest)) (*Response, error)

只要传入一个创建索引的名称即可,也可以通过IndicesCreateRequest传递一些创建索引的额外信息

实例演示:

package main

import (
	"fmt"
	"log"

	"github.com/elastic/go-elasticsearch/v7"
)

// 创建索引
func CreatIndex(client *elasticsearch.Client, name string) {
	r, _ := client.API.Indices.Create(name)
	fmt.Printf("r: %v\n", r)
}

func main() {
	es, err := elasticsearch.NewDefaultClient()
	if err != nil {
		log.Fatalf("获取es客户端错误: %s", err)
	}
	CreatIndex(es, "es_test")
}

运行结果:

[Running] go run "e:\golang开发学习\es\main.go"
r: [200 OK] {"acknowledged":true,"shards_acknowledged":true,"index":"es_test"}

[Done] exited with code=0 in 3.902 seconds

查询索引

查询索引函数如下:

type IndicesGet func(index []string, o ...func(*IndicesGetRequest)) (*Response, error)

传入需要查询的字符串切片即可

实例演示:

package main

import (
	"fmt"
	"log"

	"github.com/elastic/go-elasticsearch/v7"
)

// 查询索引
func GetIndex(client *elasticsearch.Client, name string) {
	r, _ := client.API.Indices.Get([]string{name})
	fmt.Printf("r: %v\n", r)
}

func main() {
	es, err := elasticsearch.NewDefaultClient()
	if err != nil {
		log.Fatalf("获取es客户端错误: %s", err)
	}
	GetIndex(es, "es_test")
}

运行结果:

[Running] go run "e:\golang开发学习\es\main.go"
r: [200 OK] {"es_test":{"aliases":{},"mappings":{},"settings":{"index":{"creation_date":"1663999135597","number_of_shards":"1","number_of_replicas":"1","uuid":"Mp9txec1R1Co4AONcoofGw","version":{"created":"7080199"},"provided_name":"es_test"}}}}

[Done] exited with code=0 in 1.751 seconds

删除索引

删除索引函数如下:

type IndicesDelete func(index []string, o ...func(*IndicesDeleteRequest)) (*Response, error)

传入需要删除的索引的字符串切片即可

实例演示:

package main

import (
	"fmt"
	"log"

	"github.com/elastic/go-elasticsearch/v7"
)

// 删除索引
func DelIndex(client *elasticsearch.Client, name string) {
	r, _ := client.API.Indices.Delete([]string{name})
	fmt.Printf("r: %v\n", r)
}

func main() {
	es, err := elasticsearch.NewDefaultClient()
	if err != nil {
		log.Fatalf("获取es客户端错误: %s", err)
	}

	DelIndex(es, "es_test")
}

运行结果:

[Running] go run "e:\golang开发学习\es\main.go"
r: [200 OK] {"acknowledged":true}

[Done] exited with code=0 in 1.95 seconds

Golang操作ES文档

插入文档

在这个章节中,我将一步一步地指导如何如何使用 go-elasticsearch 驱动来把文档导入到 Elasticsearch 中。

步骤一:导包

package main
 
import (
"context"
"encoding/json"
"fmt"
"log"
"reflect"
"strconv"
"strings"
 
// Import the Elasticsearch library packages
"github.com/elastic/go-elasticsearch/v7"
"github.com/elastic/go-elasticsearch/v7/esapi"
)

在上面,我们使用 v7 版本,它对应于 Elastic Stack 7.x 版本的发布。

步骤二:为文档字段创捷结构体

使用 Golang struct 数据类型为要编制索引的 Elasticsearch 文档以及索引的相应字段创建框架:

// Declare a struct for Elasticsearch fields
type ElasticDocs struct {
  SomeStr string
  SomeInt int
  SomeBool bool
}

步骤三:将结构体转换为JSON字符串

接下来,让我们看一个简单的函数,它将 Elasticsearch struct 文档实例转换为 JSON 字符串。 下面显示的代码可能看起来有些复杂,但是实际上发生的事情很简单–所有功能所做的就是将结构转换为字符串文字,然后将该字符串传递给 Golang 的 json.Marshal() 方法以使其返回字符串的JSON编码:

// structs to JSON 
func jsonStruct(doc ElasticDocs) string {
	// Create struct instance of the Elasticsearch fields struct object
	docStruct := &ElasticDocs{
		SomeStr: doc.SomeStr,
		SomeInt: doc.SomeInt,
		SomeBool: doc.SomeBool,
	}
	
	fmt.Println("\ndocStruct:", docStruct)
	fmt.Println("docStruct TYPE:", reflect.TypeOf(docStruct))
	
	// Marshal the struct to JSON and check for errors
	b, err := json.Marshal(docStruct)
	if err != nil {
		fmt.Println("json.Marshal ERROR:", err)
		return string(err.Error())
	}
	
	return string(b)
}

步骤四:创建 Elasticsearch Golang 客户端实例

为 API 调用创建一个新的上下文对象,并为 Elasticsearch 文档创建一个 map 对象:

func main() {
 
	// 允许日志输出的自定义格式
	log.SetFlags(0)
	
	// 为API调用创建上下文对象
	ctx := context.Background()
	
	// 为Elasticsearch文档创建映射
	var (
		docMap map[string]interface{}
	)
 
	fmt.Println("docMap:", docMap)
	fmt.Println("docMap TYPE:", reflect.TypeOf(docMap))

步骤五:实例化 Elasticsearch 客户端配置和 Golang 客户端实例

实例化一个新的 Elasticsearch 配置对象。 确保将正确的主机和端口信息以及任何用户名或密码传递给其 “Adressess” 属性。

	// 声明Elasticsearch配置
	cfg := elasticsearch.Config{
		Addresses: []string{
		"http://localhost:9200",
		},
		Username: "Psych",
		Password: "666",
	}
	
	// 实例化新的Elasticsearch客户端对象实例
	client, err := elasticsearch.NewClient(cfg)
	
	if err != nil {
		fmt.Println("Elasticsearch connection error:", err)
	}

步骤六:检查与 Elasticsearch 的连接

	// 让客户端实例返回响应
	res, err := client.Info()
 
	// 将响应反序列化为映射。
	if err != nil {
		log.Fatalf("client.Info() ERROR:", err)
	} else {
		log.Printf("client response:", res)
	}

步骤七:创建 Elasticsearch 结构文档并将其放入数组

声明一个空字符串数组,以存储当前以 JSON 字符串表示的 Elasticsearch 文档。 以下代码显示了一些将用于索引的 Elasticsearch 文档示例。 要设置其字段的值,你需要做的就是修改结构实例的属性:

	// 为文档字符串声明空数组
	var docs []string
 
	// 使用结构声明要索引的文档
	doc1 := ElasticDocs{}
	doc1.SomeStr = "Some Value"
	doc1.SomeInt = 123456
	doc1.SomeBool = true
 
	doc2 := ElasticDocs{}
	doc2.SomeStr = "Another Value"
	doc2.SomeInt = 42
	doc2.SomeBool = false	

将这些文档实例传递给我们先前声明的 jsonStruct() 函数,并使它们返回代表每个文档的 JSON 字符串。 然后,我们将使用 Golang 的 append() 函数将 JSON 字符串添加到字符串数组中:

	// document struct objects to JSON string
	docStr1 := jsonStruct(doc1)
	docStr2 := jsonStruct(doc2)
 
	// Append the doc strings to an array
	docs = append(docs, docStr1)
	docs = append(docs, docStr2)

步骤八:迭代文档数组并调用 Golang 客户端的 IndexRequest() 方法

对已经建立好的文档数组进行迭代,并在进行过程中向 Elasticsearch 集群发出 API 请求。 这些API调用将通过调用 Golang 驱动程序的 esapi.IndexRequest() 方法来索引文档:

	// 迭代文档数组
	for i, bod := range docs {
		fmt.Println("\nDOC _id:", i+1)
		fmt.Println(bod)
		
		// 实例化请求对象
		req := esapi.IndexRequest {
			Index: "some_index",
			DocumentID: strconv.Itoa(i + 1),
			Body: strings.NewReader(bod),
			Refresh: "true",
		}
 
		fmt.Println(reflect.TypeOf(req))

在上面一定要注意的是:我们设置 Refresh 为 true。这在实际的使用中并不建议,原因是每次写入的时候都会 refresh。当我们面对大量的数据时,这样的操作会造成效率的底下。

步骤九:检查 IndexRequest() 方法调用是否返回任何错误

在文档数组上进行迭代的最后一步是从 API 调用中获取响应,并检查是否存在错误:

		// 从请求返回API响应对象
		res, err := req.Do(ctx, client)
		if err != nil {
			log.Fatalf("IndexRequest ERROR: %s", err)
		}
 
		defer res.Body.Close()

在下面显示的代码中,如果没有错误返回,我们将解析 API 响应返回的结果对象:

		if res.IsError() {
			log.Printf("%s ERROR indexing document ID=%d", res.Status(), i+1)
		} else {
			
			// 将响应反序列化为映射。
			var resMap map[string]interface{}
			if err := json.NewDecoder(res.Body).Decode(&resMap); err != nil {
				log.Printf("Error parsing the response body: %s", err)
			} else {
				log.Printf("\nIndexRequest() RESPONSE:")
				// 打印响应状态和索引文档版本。
				fmt.Println("Status:", res.Status())
				fmt.Println("Result:", resMap["result"])
				fmt.Println("Version:", int(resMap["_version"].(float64)))
				fmt.Println("resMap:", resMap)
				fmt.Println("\n")
			}
		}
	}
}

每个文档迭代都应打印出一个map[string] interface{} 对象响应,如下所示:

resMap: map[_id:2 _index:some_index _primary_term:1 _seq_no:1 _shards:map[failed:0 successful:1 total:2] _type:_doc _version:1 forced_refresh:true result:created]

代码总结

package main
 
import (
"context"
"encoding/json"
"fmt"
"log"
"reflect"
"strconv"
"strings"
 
// Import the Elasticsearch library packages
"github.com/elastic/go-elasticsearch/v7"
"github.com/elastic/go-elasticsearch/v7/esapi"
)
 
// Declare a struct for Elasticsearch fields
type ElasticDocs struct {
	SomeStr string
	SomeInt int
	SomeBool bool
}
 
// A function for marshaling structs to JSON string
func jsonStruct(doc ElasticDocs) string {
	// Create struct instance of the Elasticsearch fields struct object
	docStruct := &ElasticDocs{
		SomeStr: doc.SomeStr,
		SomeInt: doc.SomeInt,
		SomeBool: doc.SomeBool,
	}
	
	fmt.Println("\ndocStruct:", docStruct)
	fmt.Println("docStruct TYPE:", reflect.TypeOf(docStruct))
	
	// Marshal the struct to JSON and check for errors
	b, err := json.Marshal(docStruct)
	if err != nil {
		fmt.Println("json.Marshal ERROR:", err)
		return string(err.Error())
	}
 
	return string(b)
}
 
func main() {
 
	// Allow for custom formatting of log output
	log.SetFlags(0)
	
	// Create a context object for the API calls
	ctx := context.Background()
	
	// Create a mapping for the Elasticsearch documents
	var (
		docMap map[string]interface{}
	)
 
	fmt.Println("docMap:", docMap)
	fmt.Println("docMap TYPE:", reflect.TypeOf(docMap))
 
	// Declare an Elasticsearch configuration
	cfg := elasticsearch.Config{
		Addresses: []string{
		"http://localhost:9200",
		},
		Username: "user",
		Password: "pass",
	}
	
	// Instantiate a new Elasticsearch client object instance
	client, err := elasticsearch.NewClient(cfg)
	
	if err != nil {
		fmt.Println("Elasticsearch connection error:", err)
	}
 
	// Have the client instance return a response
	res, err := client.Info()
 
	// Deserialize the response into a map.
	if err != nil {
		log.Fatalf("client.Info() ERROR:", err)
	} else {
		log.Printf("client response:", res)
	}
 
	// Declare empty array for the document strings
	var docs []string
 
	// Declare documents to be indexed using struct
	doc1 := ElasticDocs{}
	doc1.SomeStr = "Some Value"
	doc1.SomeInt = 123456
	doc1.SomeBool = true
 
	doc2 := ElasticDocs{}
	doc2.SomeStr = "Another Value"
	doc2.SomeInt = 42
	doc2.SomeBool = false	
 
	// Marshal Elasticsearch document struct objects to JSON string
	docStr1 := jsonStruct(doc1)
	docStr2 := jsonStruct(doc2)
 
	// Append the doc strings to an array
	docs = append(docs, docStr1)
	docs = append(docs, docStr2)
 
	// Iterate the array of string documents
	for i, bod := range docs {
		fmt.Println("\nDOC _id:", i+1)
		fmt.Println(bod)
		
		// Instantiate a request object
		req := esapi.IndexRequest {
			Index: "some_index",
			DocumentID: strconv.Itoa(i + 1),
			Body: strings.NewReader(bod),
			Refresh: "true",
		}
 
		fmt.Println(reflect.TypeOf(req))
 
		// Return an API response object from request
		res, err := req.Do(ctx, client)
		if err != nil {
			log.Fatalf("IndexRequest ERROR: %s", err)
		}
 
		defer res.Body.Close()
 
		if res.IsError() {
			log.Printf("%s ERROR indexing document ID=%d", res.Status(), i+1)
		} else {
			
			// Deserialize the response into a map.
			var resMap map[string]interface{}
			if err := json.NewDecoder(res.Body).Decode(&resMap); err != nil {
				log.Printf("Error parsing the response body: %s", err)
			} else {
				log.Printf("\nIndexRequest() RESPONSE:")
				// Print the response status and indexed document version.
				fmt.Println("Status:", res.Status())
				fmt.Println("Result:", resMap["result"])
				fmt.Println("Version:", int(resMap["_version"].(float64)))
				fmt.Println("resMap:", resMap)
				fmt.Println("\n")
			}
		}
	}
}

运行结果

[Running] go run "e:\golang开发学习\es\document\main.go"
docMap: map[]
docMap TYPE: map[string]interface {}
client response:%!(EXTRA *esapi.Response=[200 OK] {
  "name" : "MORAX",
  "cluster_name" : "elasticsearch",
  "cluster_uuid" : "HoU0Tw3WTiSMD2GRzezqnw",
  "version" : {
    "number" : "7.8.1",
    "build_flavor" : "default",
    "build_type" : "zip",
    "build_hash" : "b5ca9c58fb664ca8bf9e4057fc229b3396bf3a89",
    "build_date" : "2020-07-21T16:40:44.668009Z",
    "build_snapshot" : false,
    "lucene_version" : "8.5.1",
    "minimum_wire_compatibility_version" : "6.8.0",
    "minimum_index_compatibility_version" : "6.0.0-beta1"
  },
  "tagline" : "You Know, for Search"
}
)

docStruct: &{Some Value 123456 true}
docStruct TYPE: *main.ElasticDocs

docStruct: &{Another Value 42 false}
docStruct TYPE: *main.ElasticDocs

DOC _id: 1
{"SomeStr":"Some Value","SomeInt":123456,"SomeBool":true}
esapi.IndexRequest

IndexRequest() RESPONSE:
Status: 201 Created
Result: created
Version: 1
resMap: map[_id:1 _index:some_index _primary_term:1 _seq_no:0 _shards:map[failed:0 successful:1 total:2] _type:_doc _version:1 forced_refresh:true result:created]



DOC _id: 2
{"SomeStr":"Another Value","SomeInt":42,"SomeBool":false}
esapi.IndexRequest

IndexRequest() RESPONSE:
Status: 201 Created
Result: created
Version: 1
resMap: map[_id:2 _index:some_index _primary_term:1 _seq_no:1 _shards:map[failed:0 successful:1 total:2] _type:_doc _version:1 forced_refresh:true result:created]



[Done] exited with code=0 in 3.3 seconds

postman中查看插入的数据

在这里插入图片描述

查询文档

查询在 SomeStr 这个字段含有 Another 的文档,在 main.go 里添加如下的代码:

    // Search for the indexed document
    // Build the request body
    var buf bytes.Buffer
    query := map[string]interface{}{
        "query": map[string]interface{}{
            "match": map[string]interface{}{
                "SomeStr": "Another",
            },
        },
    }
 
    if err := json.NewEncoder(&buf).Encode(query); err != nil {
        log.Fatalf("Error encoding query: %s", err)
    }
 
    // Perform the search request.
    res, err = client.Search(
        client.Search.WithContext(context.Background()),
        client.Search.WithIndex("some_index"),
        client.Search.WithBody(&buf),
        client.Search.WithTrackTotalHits(true),
        client.Search.WithPretty(),
    )
 
    if err != nil {
        log.Fatalf("Error getting response: %s", err)
    }
 
    defer res.Body.Close()
 
    if res.IsError() {
        var e map[string]interface{}
        if err := json.NewDecoder(res.Body).Decode(&e); err != nil {
            log.Fatalf("Error parsing the response body: %s", err)
        } else {
            // Print the response status and error information.
            log.Fatalf("[%s] %s: %s",
                res.Status(),
                e["error"].(map[string]interface{})["type"],
                e["error"].(map[string]interface{})["reason"],
            )
        }
    }
 
 
    var  r map[string]interface{}
    if err := json.NewDecoder(res.Body).Decode(&r); err != nil {
        log.Fatalf("Error parsing the response body: %s", err)
    }
 
    // Print the response status, number of results, and request duration.
    log.Printf(
        "[%s] %d hits; took: %dms",
        res.Status(),
        int(r["hits"].(map[string]interface{})["total"].(map[string]interface{})["value"].(float64)),
        int(r["took"].(float64)),
    )
 
    // Print the ID and document source for each hit.
    for _, hit := range r["hits"].(map[string]interface{})["hits"].([]interface{}) {
        log.Printf(" * ID=%s, %s", hit.(map[string]interface{})["_id"], hit.(map[string]interface{})["_source"])
    }

运行代码后,可以看到如下新添加的结果:

[200 OK] 1 hits; took: 10ms
 * ID=2, map[SomeBool:%!s(bool=false) SomeInt:%!s(float64=42) SomeStr:Another Value]

删除文档

在 main.go 文件中,我们添加如下的代码来删除文档 id 为 1 的文档:

  // Set up the request object.
    req := esapi.DeleteRequest{
        Index:      "some_index",
        DocumentID: strconv.Itoa(1),
    }
 
    res, err = req.Do(context.Background(), client)
    if err != nil {
      log.Fatalf("Error getting response: %s", err)
    }

重新运行 main.go 应用。我们再到 postman 中去查询一下:

在这里插入图片描述

查询结果显示删除成功。

Gin集成ES

创建一个项目gin_es

mkdir gin_es
cd gin_es
code . 
go mod init gin_es
go get github.com/elastic/go-elasticsearch/v7
go get github.com/gin-gonic/gin

创建两个页面

创建一个目录templates,在该目录下创建两个页面,一个用来查询,一个用拉显示结果

templates\query.html:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>gin集成es</title>
</head>

<body>
    <form action="/query" method="post">
        keyword:<input type="text" name="keyword">
        <input type="submit" value="查询">
    </form>
</body>

</html>

templates\result.html:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>查询结果</title>
</head>

<body>
    结果:{{.result}}
</body>

</html>

处理集成逻辑

package main

import (
	"context"
	"fmt"
	"log"
	"strings"

	"github.com/elastic/go-elasticsearch/v7"
	"github.com/elastic/go-elasticsearch/v7/esapi"
	"github.com/gin-gonic/gin"
)

func Query(c *gin.Context) {
	c.HTML(200, "query.html", nil)
}

func ESQuery(keyword string) *esapi.Response {
	client, err := elasticsearch.NewDefaultClient()
	if err != nil {
		log.Fatalf("获取es客户端错误: %s", err)
	}

	// 查询条件
	query := `{"query":{"match":{"category":"` + keyword + `"}},"size":3}`

	fmt.Printf("query: %v\n", query)

	var b strings.Builder
	b.WriteString(query)
	read := strings.NewReader(b.String())

	// 查询请求
	sr := &esapi.SearchRequest{
		Index: []string{"golang"},
		Body:  read,
	}

	// 执行查询
	r, err := sr.Do(context.Background(), client)
	if err != nil {
		log.Fatalf("查询错误: %s", err)
	}
	return r
}

func DoQuery(c *gin.Context) {
	keyword := c.PostForm("keyword")

	r := ESQuery(keyword)

	c.HTML(200, "result.html", gin.H{
		"result": r,
	})
}

func main() {
	e := gin.Default()
	e.LoadHTMLGlob("templates/*")

	e.GET("/query", Query)
	e.POST("/query", DoQuery)

	e.Run()
}

测试

浏览器输入:http://localhost:8080/query进入查询页面输入护肤品进行查询:

在这里插入图片描述

点击查询获取查询结果:

在这里插入图片描述

在postman中查看shopping索引中的文档:

在这里插入图片描述

全查询结果如下:

{
    "took": 599,
    "timed_out": false,
    "_shards": {
        "total": 1,
        "successful": 1,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
        "total": {
            "value": 4,
            "relation": "eq"
        },
        "max_score": 1.0,
        "hits": [
            {
                "_index": "shopping",
                "_type": "_doc",
                "_id": "1",
                "_score": 1.0,
                "_source": {
                    "title": "sk2爽肤水",
                    "category": "护肤品",
                    "image": "https://www.tb.com",
                    "price": 899.0
                }
            },
            {
                "_index": "shopping",
                "_type": "_doc",
                "_id": "2",
                "_score": 1.0,
                "_source": {
                    "title": "眼霜",
                    "category": "化妆品",
                    "image": "https://www.tb.com",
                    "price": 249.0
                }
            },
            {
                "_index": "shopping",
                "_type": "_doc",
                "_id": "3",
                "_score": 1.0,
                "_source": {
                    "title": "拍立得",
                    "category": "数码产品",
                    "image": "https://www.tb.com",
                    "price": 299.0
                }
            },
            {
                "_index": "shopping",
                "_type": "_doc",
                "_id": "4",
                "_score": 1.0,
                "_source": {
                    "title": "科研洗面奶",
                    "category": "护肤品",
                    "image": "https://www.tb.com",
                    "price": 119.0
                }
            }
        ]
    }
}

可以看出查询护肤品结果正确。

相关文章:

  • Activity在Create阶段做的你不知道的事看源码
  • java编写一个程序,生成0~9之间的100个随机数字并且统计每一个数字的产生次数。
  • 【day11】LeetCode(力扣)练习【1652.拆炸弹】【235. 二叉搜索树的最近公共祖先】【733. 图像渲染】
  • et文件丢失怎么恢复?5种恢复方法轻松掌握
  • 运行维护-PC与笔记本性能测试
  • 硝烟后的茶歇 | 安全内生自免疫力的探索之路
  • 【LeetCode】【逆波兰表达式求解】
  • C++类和对象(中—1) —— 构造函数、析构函数、拷贝构造函数
  • SsmAjaxJson分页效果的操作(第十七课)
  • sklearn机器学习——day19
  • GrapeCity Documents for PDF (GcPDF)
  • el与data的两种写法
  • 超常用的网络工具命令汇总
  • java-php-python-springboo动物在线领养网站计算机毕业设计
  • JavaScript try-catch 处理错误和异常指南
  • Google 是如何开发 Web 框架的
  • android高仿小视频、应用锁、3种存储库、QQ小红点动画、仿支付宝图表等源码...
  • es的写入过程
  • Golang-长连接-状态推送
  • HomeBrew常规使用教程
  • HTML-表单
  • LeetCode29.两数相除 JavaScript
  • log4j2输出到kafka
  • node.js
  • PHP的Ev教程三(Periodic watcher)
  • Spark VS Hadoop:两大大数据分析系统深度解读
  • 从零开始的无人驾驶 1
  • 机器学习学习笔记一
  • 聊聊hikari连接池的leakDetectionThreshold
  • 区块链将重新定义世界
  • 学习使用ExpressJS 4.0中的新Router
  • 一个6年java程序员的工作感悟,写给还在迷茫的你
  • 移动端 h5开发相关内容总结(三)
  • 用quicker-worker.js轻松跑一个大数据遍历
  • 字符串匹配基础上
  • 回归生活:清理微信公众号
  • ​Linux·i2c驱动架构​
  • ## 临床数据 两两比较 加显著性boxplot加显著性
  • (附源码)spring boot校园拼车微信小程序 毕业设计 091617
  • (附源码)springboot炼糖厂地磅全自动控制系统 毕业设计 341357
  • (附源码)ssm基于jsp高校选课系统 毕业设计 291627
  • (最全解法)输入一个整数,输出该数二进制表示中1的个数。
  • . ./ bash dash source 这五种执行shell脚本方式 区别
  • .bat批处理(五):遍历指定目录下资源文件并更新
  • .net mvc部分视图
  • .net 程序 换成 java,NET程序员如何转行为J2EE之java基础上(9)
  • .Net 访问电子邮箱-LumiSoft.Net,好用
  • .net6解除文件上传限制。Multipart body length limit 16384 exceeded
  • .NET多线程执行函数
  • .NET企业级应用架构设计系列之应用服务器
  • .net中我喜欢的两种验证码
  • [30期] 我的学习方法
  • [AI]ChatGPT4 与 ChatGPT3.5 区别有多大
  • [AIGC] 如何建立和优化你的工作流?
  • [Asp.net MVC]Bundle合并,压缩js、css文件