乐趣区

关于golang:Elasticsearch-的-easyjson-示例

mailru/easyjson库的特点就是咱们只须要提供构造体,而后用这些构造体生成编码解码的代码。

示例的我的项目名为elasticsearch/encoding/json

一、创立 models

在我的项目中新建 model 目录,目录中新建两个文件 model.goresponse.go,在这两个文件头都增加一行代码生成正文:

//go:generate easyjson -all -snake_case $GOFILE
  • //后不能有空格

models.go:

//go:generate easyjson -all -snake_case $GOFILE

package model

import ("time")

type Article struct {
    ID        uint
    Title     string
    Body      string
    Published time.Time
    Author    *Author
}

type Author struct {
    FirstName string
    LastName  string
}

response.go:

//go:generate easyjson -all -snake_case $GOFILE

package model

type ErrorResponse struct {Info *ErrorInfo `json:"error,omitempty"`}

type ErrorInfo struct {RootCause []*ErrorInfo
    Type      string
    Reason    string
    Phase     string
}

type IndexResponse struct {
    Index   string `json:"_index"`
    ID      string `json:"_id"`
    Version int    `json:"_version"`
    Result  string
}

type SearchResponse struct {
    Took int64
    Hits struct {
        Total struct {Value int64}
        Hits []*SearchHit}
}

type SearchHit struct {
    Score   float64 `json:"_score"`
    Index   string  `json:"_index"`
    Type    string  `json:"_type"`
    Version int64   `json:"_version,omitempty"`

    Source Article `json:"_source"`
}

二、欠缺主逻辑代码

main.go:

package main

import (
    "bytes"
    "elasticsearch/encoding/json/model"
    "fmt"
    "math/rand"
    "os"
    "strconv"
    "strings"
    "time"

    "github.com/elastic/go-elasticsearch/v8"
    "github.com/elastic/go-elasticsearch/v8/esapi"
    "github.com/fatih/color"
    "github.com/mailru/easyjson"
)

var (out       = color.New(color.Reset)
    faint     = color.New(color.Faint)
    bold      = color.New(color.Bold)
    red       = color.New(color.FgRed)
    boldGreen = color.New(color.Bold, color.FgGreen)
    boldRed   = color.New(color.Bold, color.FgRed)

    articles []model.Article
    fnames   []string)

func init() {rand.Seed(time.Now().UnixNano())
}

func main() {es, err := elasticsearch.NewDefaultClient()
    if err != nil {fmt.Printf("Error creating the client: %s\n", err)
        os.Exit(2)
    }

    fnames = []string{"Alice", "John", "Mary"}

    for i, title := range []string{"One", "Two", "Three", "Four", "Five"} {
        articles = append(articles,
            model.Article{ID:        uint(i + 1),
                Title:     "Test" + title,
                Body:      "Lorem ipsum dolor sit amet, consectetur adipisicing elit",
                Published: time.Now().AddDate(i, 0, 0),
                Author: &model.Author{FirstName: fnames[rand.Intn(len(fnames))],
                    LastName:  "Smith",
                },
            })
    }

    faint.Println("Indexing articles...")
    faint.Println(strings.Repeat("━", 80))

    var b bytes.Buffer
    for _, a := range articles {b.Reset()

        // 将 article 构造体序列化为 json,json 保留到 buffer 中
        if _, err := easyjson.MarshalToWriter(a, &b); err != nil {red.Println("Error decoding response", err)
            continue
        }

        res, err := es.Index(
            "articles",
            bytes.NewReader(b.Bytes()),
            es.Index.WithDocumentID(strconv.Itoa(int(a.ID))),
            // es.Index.WithVersion(-1), // <-- 勾销此正文来触发异样
        )
        if err != nil {red.Printf("Error indexing article: %s\n", err)
            continue
        }
        defer res.Body.Close()

        if res.IsError() {printErrorResponse(res)
            os.Exit(2)
        }

        var ir model.IndexResponse
        if err := easyjson.UnmarshalFromReader(res.Body, &ir); err != nil {red.Println("Error decoding response", err)
            continue
        }

        boldGreen.Printf("[%s]", res.Status())
        fmt.Println(faint.Sprint("result=")+out.Sprint(ir.Result),
            faint.Sprint("index=")+out.Sprint(ir.Index),
            faint.Sprint("ID=")+out.Sprint(ir.ID),
            faint.Sprint("version=")+out.Sprint(ir.Version),
        )

    }

    es.Indices.Refresh(es.Indices.Refresh.WithIndex("articles"))

    faint.Println("\nSearching articles...")
    faint.Println(strings.Repeat("━", 80))

    res, err := es.Search(es.Search.WithIndex("articles"),
        es.Search.WithQuery("one OR two"),
        // es.Search.WithQuery("{{{one OR two"), // <-- 勾销此正文来触发异样
    )
    if err != nil {red.Printf("Error searching articles: %s\n", err)
        os.Exit(2)
    }
    defer res.Body.Close()

    if res.IsError() {printErrorResponse(res)
        os.Exit(2)
    }

    var sr model.SearchResponse
    if err := easyjson.UnmarshalFromReader(res.Body, &sr); err != nil {red.Println("Error decoding response", err)
        os.Exit(2)
    }

    faint.Printf("[%s] took=%d total=%d\n", res.Status(), sr.Took, sr.Hits.Total.Value)
    faint.Println(strings.Repeat("─", 80))

    for _, h := range sr.Hits.Hits {
        fmt.Println(out.Sprintf("%s,", strings.Join([]string{h.Source.Author.FirstName, h.Source.Author.LastName}, " ")),
            bold.Sprintf("%s", h.Source.Title),
            out.Sprintf("(%d)", h.Source.Published.Year()),
        )
        faint.Println(strings.Repeat("─", 80))
    }
}

// printErrorResponse 解码 es 响应,格式化后打印到终端
func printErrorResponse(res *esapi.Response) {bold.Printf("[%s]", res.Status())

    var e model.ErrorResponse
    if err := easyjson.UnmarshalFromReader(res.Body, &e); err != nil {red.Println("Error decoding response:", err)
        return
    }
    boldRed.Print(e.Info.RootCause[0].Type)
    faint.Print(">")
    fmt.Println(e.Info.RootCause[0].Reason)
}

三、生成代码

拉取我的项目中须要的库:

go mod tidy

生成代码:

go generate ./model

之后,model 目录中会多出两个文件:model_easyjson.goresponse_easyjson.go

这两个文件中的代码为 model 中的构造体实现了 mailru/easyjson 规定的一些接口。

四、运行我的项目

go run main.go
Indexing articles...
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
[200 OK] result=updated index=articles ID=1 version=36
[200 OK] result=updated index=articles ID=2 version=34
[200 OK] result=updated index=articles ID=3 version=34
[200 OK] result=updated index=articles ID=4 version=34
[200 OK] result=updated index=articles ID=5 version=34

Searching articles...
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
[200 OK] took=2 total=0
────────────────────────────────────────────────────────────────────────────────
退出移动版