爱晚枫情 發表於 2025-11-21 09:45:31

Golang操作ES进行交互的实现实例

<div id="navCategory"><h5 class="catalogue">目录</h5><ul class="first_class_ul"><li><a href="#_label0">创建项目</a></li><li><a href="#_label1">安装包</a></li><li><a href="#_label2">连接到ES</a></li><ul class="second_class_ul"><li><a href="#_lab2_2_0">运行结果</a></li></ul><li><a href="#_label3">Golang操作ES索引</a></li><ul class="second_class_ul"><li><a href="#_lab2_3_1">es API</a></li><li><a href="#_lab2_3_2">创建索引</a></li><li><a href="#_lab2_3_3">查询索引</a></li><li><a href="#_lab2_3_4">删除索引</a></li></ul><li><a href="#_label4">Golang操作ES文档</a></li><ul class="second_class_ul"><li><a href="#_lab2_4_5">插入文档</a></li><ul class="third_class_ul"><li><a href="#_label3_4_5_0">步骤一:导包</a></li><li><a href="#_label3_4_5_1">步骤二:为文档字段创捷结构体</a></li><li><a href="#_label3_4_5_2">步骤三:将结构体转换为JSON字符串</a></li><li><a href="#_label3_4_5_3">步骤四:创建 Elasticsearch Golang 客户端实例</a></li><li><a href="#_label3_4_5_4">步骤五:实例化 Elasticsearch 客户端配置和 Golang 客户端实例</a></li><li><a href="#_label3_4_5_5">步骤六:检查与 Elasticsearch 的连接</a></li><li><a href="#_label3_4_5_6">步骤七:创建 Elasticsearch 结构文档并将其放入数组</a></li><li><a href="#_label3_4_5_7">步骤八:迭代文档数组并调用 Golang 客户端的IndexRequest()方法</a></li><li><a href="#_label3_4_5_8">步骤九:检查 IndexRequest() 方法调用是否返回任何错误</a></li><li><a href="#_label3_4_5_9">代码总结</a></li><li><a href="#_label3_4_5_10">运行结果</a></li><li><a href="#_label3_4_5_11">postman中查看插入的数据</a></li></ul><li><a href="#_lab2_4_6">查询文档</a></li><ul class="third_class_ul"></ul><li><a href="#_lab2_4_7">删除文档</a></li><ul class="third_class_ul"></ul></ul><li><a href="#_label5">Gin集成ES</a></li><ul class="second_class_ul"><li><a href="#_lab2_5_8">创建一个项目gin_es</a></li><ul class="third_class_ul"></ul><li><a href="#_lab2_5_9">创建两个页面</a></li><ul class="third_class_ul"></ul><li><a href="#_lab2_5_10">处理集成逻辑</a></li><ul class="third_class_ul"></ul><li><a href="#_lab2_5_11">测试</a></li><ul class="third_class_ul"></ul></ul></ul></div><p class="maodian"><a name="_label0"></a></p><h2>创建项目</h2>
<p>创建一个项目<code>demo</code>,初始化项目<code>go mod init demo</code></p>
<p class="maodian"><a name="_label1"></a></p><h2>安装包</h2>
<div class="jb51code"><pre class="brush:go;">go get github.com/elastic/go-elasticsearch/v7
</pre></div>
<p class="maodian"><a name="_label2"></a></p><h2>连接到ES</h2>
<div class="jb51code"><pre class="brush:go;">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())
}
</pre></div>
<p class="maodian"><a name="_lab2_2_0"></a></p><h3>运行结果</h3>
<div class="jb51code"><pre class="brush:plain;"> go run "e:\golang开发学习\es\main.go"
2022/09/24 13:16:22 7.17.1
2022/09/24 13:16:22 {
"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"
}
&lt;nil&gt;

exited with code=0 in 2.516 seconds
</pre></div>
<p class="maodian"><a name="_label3"></a></p><h2>Golang操作ES索引</h2>
<p class="maodian"><a name="_lab2_3_1"></a></p><h3>es API</h3>
<p>我们获得es客户端实例后,通过客户端实例可以获得es api,内容如下:</p>
<div class="jb51code"><pre class="brush:go;">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
        DataFrameTransformDeprecatedPreviewTransformDataFrameTransformDeprecatedPreviewTransform
        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
}
</pre></div>
<p>API结构体里面包含了Indices,内容如下:</p>
<div class="jb51code"><pre class="brush:go;">// 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
}
</pre></div>
<p>该结构体包含了操作索引的一些方法,例如:创建索引<code>Create</code>、查询索引<code>Get</code>、删除索引<code>Delete</code>等</p>
<p class="maodian"><a name="_lab2_3_2"></a></p><h3>创建索引</h3>
<p>创建索引函数如下:</p>
<div class="jb51code"><pre class="brush:go;">type IndicesCreate func(index string, o ...func(*IndicesCreateRequest)) (*Response, error)
</pre></div>
<p>只要传入一个创建索引的名称即可,也可以通过<code>IndicesCreateRequest</code>传递一些创建索引的额外信息</p>
<p>实例演示:</p>
<div class="jb51code"><pre class="brush:go;">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")
}
</pre></div>
<p>运行结果:</p>
<div class="jb51code"><pre class="brush:plain;"> go run "e:\golang开发学习\es\main.go"
r: {"acknowledged":true,"shards_acknowledged":true,"index":"es_test"}

exited with code=0 in 3.902 seconds
</pre></div>
<p class="maodian"><a name="_lab2_3_3"></a></p><h3>查询索引</h3>
<p>查询索引函数如下:</p>
<div class="jb51code"><pre class="brush:go;">type IndicesGet func(index []string, o ...func(*IndicesGetRequest)) (*Response, error)
</pre></div>
<p>传入需要查询的字符串切片即可</p>
<p>实例演示:</p>
<div class="jb51code"><pre class="brush:go;">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")
}
</pre></div>
<p>运行结果:</p>
<div class="jb51code"><pre class="brush:plain;"> go run "e:\golang开发学习\es\main.go"
r: {"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"}}}}

exited with code=0 in 1.751 seconds
</pre></div>
<p class="maodian"><a name="_lab2_3_4"></a></p><h3>删除索引</h3>
<p>删除索引函数如下:</p>
<div class="jb51code"><pre class="brush:go;">type IndicesDelete func(index []string, o ...func(*IndicesDeleteRequest)) (*Response, error)
</pre></div>
<p>传入需要删除的索引的字符串切片即可</p>
<p>实例演示:</p>
<div class="jb51code"><pre class="brush:go;">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")
}
</pre></div>
<p>运行结果:</p>
<div class="jb51code"><pre class="brush:plain;"> go run "e:\golang开发学习\es\main.go"
r: {"acknowledged":true}

exited with code=0 in 1.95 seconds
</pre></div>
<p class="maodian"><a name="_label4"></a></p><h2>Golang操作ES文档</h2>
<p class="maodian"><a name="_lab2_4_5"></a></p><h3>插入文档</h3>
<p>在这个章节中,我将一步一步地指导如何如何使用 go-elasticsearch 驱动来把文档导入到 Elasticsearch 中。</p>
<p class="maodian"><a name="_label3_4_5_0"></a></p><h4>步骤一:导包</h4>
<div class="jb51code"><pre class="brush:go;">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"
)
</pre></div>
<p>在上面,我们使用 v7 版本,它对应于 Elastic Stack 7.x 版本的发布。</p>
<p class="maodian"><a name="_label3_4_5_1"></a></p><h4>步骤二:为文档字段创捷结构体</h4>
<p>使用 Golang struct 数据类型为要编制索引的 Elasticsearch 文档以及索引的相应字段创建框架:</p>
<div class="jb51code"><pre class="brush:go;">// Declare a struct for Elasticsearch fields
type ElasticDocs struct {
SomeStr string
SomeInt int
SomeBool bool
}
</pre></div>
<p class="maodian"><a name="_label3_4_5_2"></a></p><h4>步骤三:将结构体转换为JSON字符串</h4>
<p>接下来,让我们看一个简单的函数,它将 Elasticsearch struct 文档实例转换为 JSON 字符串。 下面显示的代码可能看起来有些复杂,但是实际上发生的事情很简单&ndash;所有功能所做的就是将结构转换为字符串文字,然后将该字符串传递给 Golang 的 <code>json.Marshal()</code> 方法以使其返回字符串的JSON编码:</p>
<div class="jb51code"><pre class="brush:go;">// structs to JSON
func jsonStruct(doc ElasticDocs) string {
        // Create struct instance of the Elasticsearch fields struct object
        docStruct := &amp;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)
}
</pre></div>
<p class="maodian"><a name="_label3_4_5_3"></a></p><h4>步骤四:创建 Elasticsearch Golang 客户端实例</h4>
<p>为 API 调用创建一个新的上下文对象,并为 Elasticsearch 文档创建一个 map 对象:</p>
<div class="jb51code"><pre class="brush:go;">func main() {

        // 允许日志输出的自定义格式
        log.SetFlags(0)
       
        // 为API调用创建上下文对象
        ctx := context.Background()
       
        // 为Elasticsearch文档创建映射
        var (
                docMap mapinterface{}
        )

        fmt.Println("docMap:", docMap)
        fmt.Println("docMap TYPE:", reflect.TypeOf(docMap))
</pre></div>
<p class="maodian"><a name="_label3_4_5_4"></a></p><h4>步骤五:实例化 Elasticsearch 客户端配置和 Golang 客户端实例</h4>
<p>实例化一个新的 Elasticsearch 配置对象。 确保将正确的主机和端口信息以及任何用户名或密码传递给其 &ldquo;Adressess&rdquo; 属性。</p>
<div class="jb51code"><pre class="brush:go;">        // 声明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)
        }
</pre></div>
<p class="maodian"><a name="_label3_4_5_5"></a></p><h4>步骤六:检查与 Elasticsearch 的连接</h4>
<div class="jb51code"><pre class="brush:go;">        // 让客户端实例返回响应
        res, err := client.Info()

        // 将响应反序列化为映射。
        if err != nil {
                log.Fatalf("client.Info() ERROR:", err)
        } else {
                log.Printf("client response:", res)
        }
</pre></div>
<p class="maodian"><a name="_label3_4_5_6"></a></p><h4>步骤七:创建 Elasticsearch 结构文档并将其放入数组</h4>
<p>声明一个空字符串数组,以存储当前以 JSON 字符串表示的 Elasticsearch 文档。 以下代码显示了一些将用于索引的 Elasticsearch 文档示例。 要设置其字段的值,你需要做的就是修改结构实例的属性:</p>
<div class="jb51code"><pre class="brush:go;">        // 为文档字符串声明空数组
        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       
</pre></div>
<p>将这些文档实例传递给我们先前声明的 jsonStruct() 函数,并使它们返回代表每个文档的 JSON 字符串。 然后,我们将使用 Golang 的 append() 函数将 JSON 字符串添加到字符串数组中:</p>
<div class="jb51code"><pre class="brush:go;">        // 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)
</pre></div>
<p class="maodian"><a name="_label3_4_5_7"></a></p><h4>步骤八:迭代文档数组并调用 Golang 客户端的IndexRequest()方法</h4>
<p>对已经建立好的文档数组进行迭代,并在进行过程中向 Elasticsearch 集群发出 API 请求。 这些API调用将通过调用 Golang 驱动程序的 esapi.IndexRequest() 方法来索引文档:</p>
<div class="jb51code"><pre class="brush:go;">        // 迭代文档数组
        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))
</pre></div>
<blockquote><p>在上面一定要注意的是:我们设置 Refresh 为 true。这在实际的使用中并不建议,原因是每次写入的时候都会 refresh。当我们面对大量的数据时,这样的操作会造成效率的底下。</p></blockquote>
<p class="maodian"><a name="_label3_4_5_8"></a></p><h4>步骤九:检查 IndexRequest() 方法调用是否返回任何错误</h4>
<p>在文档数组上进行迭代的最后一步是从 API 调用中获取响应,并检查是否存在错误:</p>
<div class="jb51code"><pre class="brush:go;">                // 从请求返回API响应对象
                res, err := req.Do(ctx, client)
                if err != nil {
                        log.Fatalf("IndexRequest ERROR: %s", err)
                }

                defer res.Body.Close()
</pre></div>
<p>在下面显示的代码中,如果没有错误返回,我们将解析 API 响应返回的结果对象:</p>
<div class="jb51code"><pre class="brush:go;">                if res.IsError() {
                        log.Printf("%s ERROR indexing document ID=%d", res.Status(), i+1)
                } else {
                       
                        // 将响应反序列化为映射。
                        var resMap mapinterface{}
                        if err := json.NewDecoder(res.Body).Decode(&amp;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")
                        }
                }
        }
}
</pre></div>
<p>每个文档迭代都应打印出一个<code>map interface{}</code> 对象响应,如下所示:</p>
<div class="jb51code"><pre class="brush:go;">resMap: map _type:_doc _version:1 forced_refresh:true result:created]
</pre></div>
<p class="maodian"><a name="_label3_4_5_9"></a></p><h4>代码总结</h4>
<div class="jb51code"><pre class="brush:go;">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 := &amp;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 mapinterface{}
        )

        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 mapinterface{}
                        if err := json.NewDecoder(res.Body).Decode(&amp;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")
                        }
                }
        }
}
</pre></div>
<p class="maodian"><a name="_label3_4_5_10"></a></p><h4>运行结果</h4>
<div class="jb51code"><pre class="brush:go;"> go run "e:\golang开发学习\es\document\main.go"
docMap: map[]
docMap TYPE: mapinterface {}
client response:%!(EXTRA *esapi.Response= {
"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: &amp;{Some Value 123456 true}
docStruct TYPE: *main.ElasticDocs

docStruct: &amp;{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 _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 _type:_doc _version:1 forced_refresh:true result:created]



exited with code=0 in 3.3 seconds
</pre></div>
<p class="maodian"><a name="_label3_4_5_11"></a></p><h4>postman中查看插入的数据</h4>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202511/2025112109423254.png" /></p>
<p class="maodian"><a name="_lab2_4_6"></a></p><h3>查询文档</h3>
<p>查询在 SomeStr 这个字段含有 <strong>Another</strong> 的文档,在 main.go 里添加如下的代码:</p>
<div class="jb51code"><pre class="brush:go;">    // Search for the indexed document
    // Build the request body
    var buf bytes.Buffer
    query := mapinterface{}{
      "query": mapinterface{}{
            "match": mapinterface{}{
                "SomeStr": "Another",
            },
      },
    }

    if err := json.NewEncoder(&amp;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(&amp;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 mapinterface{}
      if err := json.NewDecoder(res.Body).Decode(&amp;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"].(mapinterface{})["type"],
                e["error"].(mapinterface{})["reason"],
            )
      }
    }


    varr mapinterface{}
    if err := json.NewDecoder(res.Body).Decode(&amp;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"].(mapinterface{})["total"].(mapinterface{})["value"].(float64)),
      int(r["took"].(float64)),
    )

    // Print the ID and document source for each hit.
    for _, hit := range r["hits"].(mapinterface{})["hits"].([]interface{}) {
      log.Printf(" * ID=%s, %s", hit.(mapinterface{})["_id"], hit.(mapinterface{})["_source"])
    }
</pre></div>
<p>运行代码后,可以看到如下新添加的结果:</p>
<div class="jb51code"><pre class="brush:plain;"> 1 hits; took: 10ms
* ID=2, map
</pre></div>
<p class="maodian"><a name="_lab2_4_7"></a></p><h3>删除文档</h3>
<p>在 main.go 文件中,我们添加如下的代码来删除文档 id 为 1 的文档:</p>
<div class="jb51code"><pre class="brush:go;">// 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)
    }
</pre></div>
<p>重新运行 main.go 应用。我们再到 postman 中去查询一下:</p>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202511/2025112109423227.png" /></p>
<p>查询结果显示删除成功。</p>
<p class="maodian"><a name="_label5"></a></p><h2>Gin集成ES</h2>
<p class="maodian"><a name="_lab2_5_8"></a></p><h3>创建一个项目gin_es</h3>
<div class="jb51code"><pre class="brush:go;">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
</pre></div>
<p class="maodian"><a name="_lab2_5_9"></a></p><h3>创建两个页面</h3>
<p>创建一个目录templates,在该目录下创建两个页面,一个用来查询,一个用拉显示结果</p>
<p>templates\query.html:</p>
<div class="jb51code"><pre class="brush:xhtml;">&lt;!DOCTYPE html&gt;
&lt;html lang="en"&gt;

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

&lt;body&gt;
    &lt;form action="/query" method="post"&gt;
      keyword:&lt;input type="text" name="keyword"&gt;
      &lt;input type="submit" value="查询"&gt;
    &lt;/form&gt;
&lt;/body&gt;

&lt;/html&gt;
</pre></div>
<p>templates\result.html:</p>
<div class="jb51code"><pre class="brush:xhtml;">&lt;!DOCTYPE html&gt;
&lt;html lang="en"&gt;

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

&lt;body&gt;
    结果:{{.result}}
&lt;/body&gt;

&lt;/html&gt;
</pre></div>
<p class="maodian"><a name="_lab2_5_10"></a></p><h3>处理集成逻辑</h3>
<div class="jb51code"><pre class="brush:go;">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 := &amp;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()
}
</pre></div>
<p class="maodian"><a name="_lab2_5_11"></a></p><h3>测试</h3>
<p>浏览器输入:http://localhost:8080/query进入查询页面输入<code>护肤品</code>进行查询:</p>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202511/2025112109423290.png" /></p>
<p>点击查询获取查询结果:</p>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202511/2025112109423217.png" /></p>
<p>在postman中查看shopping索引中的文档:</p>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202511/2025112109423145.png" /></p>
<p>全查询结果如下:</p>
<div class="jb51code"><pre class="brush:json;">{
    "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
                }
            }
      ]
    }
}
</pre></div>
<p>可以看出查询<code>护肤品</code>结果正确。</p>
頁: [1]
查看完整版本: Golang操作ES进行交互的实现实例