Golang操作ES進(jìn)行交互的實(shí)現(xiàn)實(shí)例
創(chuàng)建項(xiàng)目
創(chuàng)建一個(gè)項(xiàng)目demo,初始化項(xiàng)目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服務(wù)器
if err != nil {
panic(err)
}
log.Println(elasticsearch.Version)
log.Println(es.Info())
}
運(yùn)行結(jié)果
[Running] go run "e:\golang開發(fā)學(xué)習(xí)\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客戶端實(shí)例后,通過客戶端實(shí)例可以獲得es api,內(nèi)容如下:
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結(jié)構(gòu)體里面包含了Indices,內(nèi)容如下:
// 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
}
該結(jié)構(gòu)體包含了操作索引的一些方法,例如:創(chuàng)建索引Create、查詢索引Get、刪除索引Delete等
創(chuàng)建索引
創(chuàng)建索引函數(shù)如下:
type IndicesCreate func(index string, o ...func(*IndicesCreateRequest)) (*Response, error)
只要傳入一個(gè)創(chuàng)建索引的名稱即可,也可以通過IndicesCreateRequest傳遞一些創(chuàng)建索引的額外信息
實(shí)例演示:
package main
import (
"fmt"
"log"
"github.com/elastic/go-elasticsearch/v7"
)
// 創(chuàng)建索引
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客戶端錯(cuò)誤: %s", err)
}
CreatIndex(es, "es_test")
}
運(yùn)行結(jié)果:
[Running] go run "e:\golang開發(fā)學(xué)習(xí)\es\main.go"
r: [200 OK] {"acknowledged":true,"shards_acknowledged":true,"index":"es_test"}
[Done] exited with code=0 in 3.902 seconds
查詢索引
查詢索引函數(shù)如下:
type IndicesGet func(index []string, o ...func(*IndicesGetRequest)) (*Response, error)
傳入需要查詢的字符串切片即可
實(shí)例演示:
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客戶端錯(cuò)誤: %s", err)
}
GetIndex(es, "es_test")
}
運(yùn)行結(jié)果:
[Running] go run "e:\golang開發(fā)學(xué)習(xí)\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
刪除索引
刪除索引函數(shù)如下:
type IndicesDelete func(index []string, o ...func(*IndicesDeleteRequest)) (*Response, error)
傳入需要?jiǎng)h除的索引的字符串切片即可
實(shí)例演示:
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客戶端錯(cuò)誤: %s", err)
}
DelIndex(es, "es_test")
}
運(yùn)行結(jié)果:
[Running] go run "e:\golang開發(fā)學(xué)習(xí)\es\main.go"
r: [200 OK] {"acknowledged":true}
[Done] exited with code=0 in 1.95 seconds
Golang操作ES文檔
插入文檔
在這個(gè)章節(jié)中,我將一步一步地指導(dǎo)如何如何使用 go-elasticsearch 驅(qū)動(dòng)來把文檔導(dǎo)入到 Elasticsearch 中。
步驟一:導(dǎo)包
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 版本,它對(duì)應(yīng)于 Elastic Stack 7.x 版本的發(fā)布。
步驟二:為文檔字段創(chuàng)捷結(jié)構(gòu)體
使用 Golang struct 數(shù)據(jù)類型為要編制索引的 Elasticsearch 文檔以及索引的相應(yīng)字段創(chuàng)建框架:
// Declare a struct for Elasticsearch fields
type ElasticDocs struct {
SomeStr string
SomeInt int
SomeBool bool
}
步驟三:將結(jié)構(gòu)體轉(zhuǎn)換為JSON字符串
接下來,讓我們看一個(gè)簡單的函數(shù),它將 Elasticsearch struct 文檔實(shí)例轉(zhuǎn)換為 JSON 字符串。 下面顯示的代碼可能看起來有些復(fù)雜,但是實(shí)際上發(fā)生的事情很簡單–所有功能所做的就是將結(jié)構(gòu)轉(zhuǎn)換為字符串文字,然后將該字符串傳遞給 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)
}
步驟四:創(chuàng)建 Elasticsearch Golang 客戶端實(shí)例
為 API 調(diào)用創(chuàng)建一個(gè)新的上下文對(duì)象,并為 Elasticsearch 文檔創(chuàng)建一個(gè) map 對(duì)象:
func main() {
// 允許日志輸出的自定義格式
log.SetFlags(0)
// 為API調(diào)用創(chuàng)建上下文對(duì)象
ctx := context.Background()
// 為Elasticsearch文檔創(chuàng)建映射
var (
docMap map[string]interface{}
)
fmt.Println("docMap:", docMap)
fmt.Println("docMap TYPE:", reflect.TypeOf(docMap))
步驟五:實(shí)例化 Elasticsearch 客戶端配置和 Golang 客戶端實(shí)例
實(shí)例化一個(gè)新的 Elasticsearch 配置對(duì)象。 確保將正確的主機(jī)和端口信息以及任何用戶名或密碼傳遞給其 “Adressess” 屬性。
// 聲明Elasticsearch配置
cfg := elasticsearch.Config{
Addresses: []string{
"http://localhost:9200",
},
Username: "Psych",
Password: "666",
}
// 實(shí)例化新的Elasticsearch客戶端對(duì)象實(shí)例
client, err := elasticsearch.NewClient(cfg)
if err != nil {
fmt.Println("Elasticsearch connection error:", err)
}
步驟六:檢查與 Elasticsearch 的連接
// 讓客戶端實(shí)例返回響應(yīng)
res, err := client.Info()
// 將響應(yīng)反序列化為映射。
if err != nil {
log.Fatalf("client.Info() ERROR:", err)
} else {
log.Printf("client response:", res)
}
步驟七:創(chuàng)建 Elasticsearch 結(jié)構(gòu)文檔并將其放入數(shù)組
聲明一個(gè)空字符串?dāng)?shù)組,以存儲(chǔ)當(dāng)前以 JSON 字符串表示的 Elasticsearch 文檔。 以下代碼顯示了一些將用于索引的 Elasticsearch 文檔示例。 要設(shè)置其字段的值,你需要做的就是修改結(jié)構(gòu)實(shí)例的屬性:
// 為文檔字符串聲明空數(shù)組
var docs []string
// 使用結(jié)構(gòu)聲明要索引的文檔
doc1 := ElasticDocs{}
doc1.SomeStr = "Some Value"
doc1.SomeInt = 123456
doc1.SomeBool = true
doc2 := ElasticDocs{}
doc2.SomeStr = "Another Value"
doc2.SomeInt = 42
doc2.SomeBool = false
將這些文檔實(shí)例傳遞給我們先前聲明的 jsonStruct() 函數(shù),并使它們返回代表每個(gè)文檔的 JSON 字符串。 然后,我們將使用 Golang 的 append() 函數(shù)將 JSON 字符串添加到字符串?dāng)?shù)組中:
// 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)
步驟八:迭代文檔數(shù)組并調(diào)用 Golang 客戶端的IndexRequest()方法
對(duì)已經(jīng)建立好的文檔數(shù)組進(jìn)行迭代,并在進(jìn)行過程中向 Elasticsearch 集群發(fā)出 API 請(qǐng)求。 這些API調(diào)用將通過調(diào)用 Golang 驅(qū)動(dòng)程序的 esapi.IndexRequest() 方法來索引文檔:
// 迭代文檔數(shù)組
for i, bod := range docs {
fmt.Println("\nDOC _id:", i+1)
fmt.Println(bod)
// 實(shí)例化請(qǐng)求對(duì)象
req := esapi.IndexRequest {
Index: "some_index",
DocumentID: strconv.Itoa(i + 1),
Body: strings.NewReader(bod),
Refresh: "true",
}
fmt.Println(reflect.TypeOf(req))
在上面一定要注意的是:我們?cè)O(shè)置 Refresh 為 true。這在實(shí)際的使用中并不建議,原因是每次寫入的時(shí)候都會(huì) refresh。當(dāng)我們面對(duì)大量的數(shù)據(jù)時(shí),這樣的操作會(huì)造成效率的底下。
步驟九:檢查 IndexRequest() 方法調(diào)用是否返回任何錯(cuò)誤
在文檔數(shù)組上進(jìn)行迭代的最后一步是從 API 調(diào)用中獲取響應(yīng),并檢查是否存在錯(cuò)誤:
// 從請(qǐng)求返回API響應(yīng)對(duì)象
res, err := req.Do(ctx, client)
if err != nil {
log.Fatalf("IndexRequest ERROR: %s", err)
}
defer res.Body.Close()
在下面顯示的代碼中,如果沒有錯(cuò)誤返回,我們將解析 API 響應(yīng)返回的結(jié)果對(duì)象:
if res.IsError() {
log.Printf("%s ERROR indexing document ID=%d", res.Status(), i+1)
} else {
// 將響應(yīng)反序列化為映射。
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:")
// 打印響應(yīng)狀態(tài)和索引文檔版本。
fmt.Println("Status:", res.Status())
fmt.Println("Result:", resMap["result"])
fmt.Println("Version:", int(resMap["_version"].(float64)))
fmt.Println("resMap:", resMap)
fmt.Println("\n")
}
}
}
}
每個(gè)文檔迭代都應(yīng)打印出一個(gè)map[string] interface{} 對(duì)象響應(yīng),如下所示:
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]
代碼總結(jié)
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")
}
}
}
}
運(yùn)行結(jié)果
[Running] go run "e:\golang開發(fā)學(xué)習(xí)\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中查看插入的數(shù)據(jù)

查詢文檔
查詢?cè)?SomeStr 這個(gè)字段含有 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"])
}
運(yùn)行代碼后,可以看到如下新添加的結(jié)果:
[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)
}
重新運(yùn)行 main.go 應(yīng)用。我們?cè)俚?postman 中去查詢一下:

查詢結(jié)果顯示刪除成功。
Gin集成ES
創(chuàng)建一個(gè)項(xiàng)目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
創(chuàng)建兩個(gè)頁面
創(chuàng)建一個(gè)目錄templates,在該目錄下創(chuàng)建兩個(gè)頁面,一個(gè)用來查詢,一個(gè)用拉顯示結(jié)果
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>查詢結(jié)果</title>
</head>
<body>
結(jié)果:{{.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客戶端錯(cuò)誤: %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())
// 查詢請(qǐng)求
sr := &esapi.SearchRequest{
Index: []string{"golang"},
Body: read,
}
// 執(zhí)行查詢
r, err := sr.Do(context.Background(), client)
if err != nil {
log.Fatalf("查詢錯(cuò)誤: %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()
}
測(cè)試
瀏覽器輸入:http://localhost:8080/query進(jìn)入查詢頁面輸入護(hù)膚品進(jìn)行查詢:

點(diǎn)擊查詢獲取查詢結(jié)果:

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

全查詢結(jié)果如下:
{
"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": "護(hù)膚品",
"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": "數(shù)碼產(chǎn)品",
"image": "https://www.tb.com",
"price": 299.0
}
},
{
"_index": "shopping",
"_type": "_doc",
"_id": "4",
"_score": 1.0,
"_source": {
"title": "科研洗面奶",
"category": "護(hù)膚品",
"image": "https://www.tb.com",
"price": 119.0
}
}
]
}
}
可以看出查詢護(hù)膚品結(jié)果正確。
到此這篇關(guān)于Golang操作ES進(jìn)行交互的實(shí)現(xiàn)實(shí)例的文章就介紹到這了,更多相關(guān)Golang操作ES內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
golang 數(shù)組去重,利用map的實(shí)現(xiàn)
這篇文章主要介紹了golang 數(shù)組去重,利用map的實(shí)現(xiàn)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-04-04
從零封裝Gin框架實(shí)現(xiàn)數(shù)據(jù)庫初始化GORM
這篇文章主要為大家介紹了從零封裝Gin框架實(shí)現(xiàn)數(shù)據(jù)庫初始化GORM,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2024-01-01
詳解golang consul-grpc 服務(wù)注冊(cè)與發(fā)現(xiàn)
這篇文章主要介紹了詳解golang consul-grpc 服務(wù)注冊(cè)與發(fā)現(xiàn),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-06-06
Win10系統(tǒng)下Golang環(huán)境搭建全過程
在編程語言的選取上,越來越多的人選擇了Golang,下面這篇文章主要給大家介紹了關(guān)于Win10系統(tǒng)下Golang環(huán)境搭建的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下2024-01-01
Skywalking-go自動(dòng)監(jiān)控增強(qiáng)使用探究
這篇文章主要介紹了Skywalking-go自動(dòng)監(jiān)控增強(qiáng)使用深入探究,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2024-01-01
Go語言并發(fā)定時(shí)任務(wù)之從Sleep到Context的8種寫法全解析
這篇文章主要為大家詳細(xì)介紹了Go語言并發(fā)定時(shí)任務(wù)之從Sleep到Context的8種寫法的相關(guān)知識(shí),文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解下2025-08-08

