连接
es_init.go
package model
import (
"context"
"fmt"
"log"
"os"
"github.com/olivere/elastic/v7"
)
func init() {
initElasticClient()
}
var host = "http://192.168.0.110:9200"
//var host = "http://127.0.0.1:9200"
var eSClient *elastic.Client
func initElasticClient() {
//elasticClient, err = elastic.NewClient(elastic.SetURL("http://127.0.0.1:9200"))
//fmt.Println("config.ElasticsearchConfig.Addr",config.ElasticsearchConfig.Host)
fmt.Println("host:", host)
errorLog := log.New(os.Stdout, "APP", log.LstdFlags)
var err error
eSClient, err = elastic.NewClient(
elastic.SetURL(host),
elastic.SetSniff(false), // SetSniff启用或禁用嗅探器(默认情况下启用)。
elastic.SetBasicAuth("", ""), // 账号密码
elastic.SetErrorLog(errorLog),
elastic.SetURL(host),
)
if err != nil {
log.Fatal("elasticsearch connect failed !", err)
return
}
do, i, _ := eSClient.Ping(host).Do(context.Background())
fmt.Println("do---->:", do)
fmt.Println("i----->:", i)
version, _ := eSClient.ElasticsearchVersion(host)
log.Println("elasticsearch connect success ! version:" + version)
//go func() {
// time.Sleep(2 * time.Second)
fmt.Println("ElasticSearch connect successful")
//}()
}
user封装
user.go
package model
import (
"context"
"encoding/json"
"errors"
"fmt"
"github.com/golang-module/carbon/v2"
"github.com/olivere/elastic/v7"
"log"
"reflect"
"strconv"
)
//参考文档:
//https://blog.csdn.net/p1049990866/article/details/117254708
type User struct {
Id int64 `json:"id"`
Name string `json:"name"`
Height float32 `json:"height"`
Age int8 `json:"age"`
State bool `json:"state"`
CreatedAt string `json:"created_at"`
UpdatedAt string `json:"updated_at"`
}
func init() {
UserAutoMigrate()
}
func UserAutoMigrate() {
//CreateIndex 创建索引
var user User
createIndexBool, err := user.CreateIndexWithSettings()
fmt.Printf("CreateIndexWithSettings success. bool:%v err:%v", createIndexBool, err)
// 更新索引 仅支持添加字段, 已有字段无法修改
//AddIndexFieldBool, err := user.AddIndexField()
//fmt.Printf("AddIndexField success. bool:%v err:%v", AddIndexFieldBool, err)
}
// TableName fofa数据库
func (User) TableName() string {
return "user"
}
//mapping=====================================
//IndexExists HEAD user 判断IndexExists是否存在
func (t *User) IndexExists() (bool, error) {
return eSClient.IndexExists(t.TableName()).Do(context.Background())
}
// DeleteIndex DELETE user 删除索引
func (t *User) DeleteIndex() (bool, error) {
indexExists, err := t.IndexExists()
if err != nil {
return false, err
}
if !indexExists {
return true, err
}
deleteIndex, err := eSClient.DeleteIndex(t.TableName()).Do(context.Background())
if err != nil {
return false, err
}
if !deleteIndex.Acknowledged {
return false, errors.New("delete index not acknowledged")
}
return true, err
}
// CreateIndexWithSettings ... 创建索引 设置分片数
/*
PUT user
{
"settings":{
"number_of_shards":1,
"number_of_replicas":0
},
"mappings":{
"properties":{
"age":{
"type":"long"
},
"height":{
"type":"float"
},
"id":{
"type":"long"
},
"name":{
"type":"text",
"fields":{
"keyword":{
"type":"keyword",
"ignore_above":256
}
}
},
"state":{
"type":"boolean"
},
"created_at":{
"type":"date",
"format":"yyyy-MM-dd HH:mm:ss||yyyy-MM-dd ||HH:mm:ss ||epoch_millis"
},
"updated_at":{
"type":"date",
"format":"yyyy-MM-dd HH:mm:ss||yyyy-MM-dd ||HH:mm:ss ||epoch_millis"
}
}
}
}
*/
func (t *User) CreateIndexWithSettings() (bool, error) {
indexExists, err := t.IndexExists()
if err != nil {
return false, err
}
if indexExists {
return true, err
}
// number_of_shards 分片数
// number_of_replicas 副本数量
mapping := `{
"settings":{
"number_of_shards":1,
"number_of_replicas":0
},
"mappings":{
"properties":{
"age":{
"type":"long"
},
"height":{
"type":"float"
},
"id":{
"type":"long"
},
"name":{
"type":"text",
"fields":{
"keyword":{
"type":"keyword",
"ignore_above":256
}
}
},
"state":{
"type":"boolean"
},
"created_at":{
"type":"date",
"format":"yyyy-MM-dd HH:mm:ss||yyyy-MM-dd ||HH:mm:ss ||epoch_millis"
},
"updated_at":{
"type":"date",
"format":"yyyy-MM-dd HH:mm:ss||yyyy-MM-dd ||HH:mm:ss ||epoch_millis"
}
}
}
}`
// Create a new index.
createIndex, err := eSClient.CreateIndex(t.TableName()).
Body(mapping).
Do(context.Background())
if err != nil {
return false, err
}
if createIndex == nil {
return false, errors.New(fmt.Sprintf("expected result to be != nil; got: %v", createIndex))
}
if !createIndex.Acknowledged {
return false, errors.New("create index not acknowledged")
}
// GetMapping Mapping.
mappingString, err := t.GetMapping()
fmt.Println("mappingString err:", err)
fmt.Println("mappingString:", mappingString)
return true, err
}
// AddIndexField ... 更新索引 仅支持添加字段, 已有字段无法修改
/*
PUT users/_mapping
{
"properties":{
"gender":{
"type":"boolean"
}
}
}
*/
func (t *User) AddIndexField() (bool, error) {
indexExists, err := t.IndexExists()
if err != nil {
return false, err
}
if !indexExists {
return false, errors.New("user indexNoExists. ")
}
// 添加字段gender字段
mapping := `{
"properties":{
"gender":{
"type":"boolean"
}
}
}`
// Create Mapping.
putresp, err := eSClient.PutMapping().Index(t.TableName()).BodyString(mapping).Do(context.TODO())
if err != nil {
return false, errors.New(fmt.Sprintf("expected put mapping to succeed; got: %v", err))
}
if putresp == nil {
return false, errors.New(fmt.Sprintf("expected put mapping response; got: %v", putresp))
}
if !putresp.Acknowledged {
return false, errors.New(fmt.Sprintf("expected put mapping ack; got: %v", putresp.Acknowledged))
}
// GetMapping Mapping.
mappingString, err := t.GetMapping()
fmt.Println("mappingString err:", err)
fmt.Println("mappingString:", mappingString)
return true, err
}
// GetMapping Mapping. GET user/_mapping?pretty 获取mapping
func (t *User) GetMapping() (mappingStr string, err error) {
// GetMapping Mapping.
getResp, err := eSClient.GetMapping().Index(t.TableName()).Do(context.TODO())
if err != nil {
return "", errors.New(fmt.Sprintf("expected get mapping to succeed; got: %v", err))
}
if getResp == nil {
return "", errors.New(fmt.Sprintf("expected get mapping response; got: %v", getResp))
}
props, ok := getResp[t.TableName()]
if !ok {
return "", errors.New(fmt.Sprintf("expected JSON root to be of type map[string]interface{}; got: %#v", props))
}
//json格式化输出
//mappingByte1, err := json.MarshalIndent(props, "", "\t")
//fmt.Printf("mappingByte1:%v \n", string(mappingByte1))
//fmt.Printf("mappingByte1 err:%v \n", err)
mappingByte, err := json.Marshal(props)
return string(mappingByte), err
}
// Reindex ... 数据迁移 将一个索引的数据迁移到另一个索引中, 一般用于索引结构发生改变时使用新索引存储数据
//更多参考文档:
// https://blog.csdn.net/goxingman/article/details/103734747
// https://www.cnblogs.com/sanduzxcvbnm/p/12084714.html
// 另外还可以指定复制哪个字段,或者排除哪些字段,或者按过滤条件复制,具体参考文档.
func (t *User) Reindex() (err error) {
type mi = map[string]interface{}
oldIndexName := t.TableName()
newIndexName := "user_test"
// GetMapping Mapping.
out, err := eSClient.Reindex().
Size(10000). //就像上面返回的结果显示的那样,它是以batch(批量)的方式来执行的。默认的批量大小为1000
Body(mi{
"source": mi{
"index": oldIndexName, //oldIndexName
},
"dest": mi{
"index": newIndexName,
},
}).Refresh("true").Do(context.Background())
//want := fmt.Sprintf(`{"dest":{"index":"%s"},"source":{"index":"%s"}}`, newIndexName, oldIndexName)
//if got != want {
// return errors.New(fmt.Sprintf("\ngot %s\nwant %s", got, want))
//}
if err != nil {
return errors.New(fmt.Sprintf("eSClient.Reindex() failed; err: %v", err))
}
b, err := json.Marshal(out)
if err != nil {
return errors.New(fmt.Sprintf("json.Marshal(out) failed; err: %v", err))
}
got := string(b)
fmt.Printf("got-->:%v \n", got)
//got-->:{"took":14,"timed_out":false,"total":7,"created":7,"deleted":0,"batches":1,"version_conflicts":0,"noops":0,"retries":{"bulk":0,"search":0},"throttled":"","throttled_millis":0,"requests_per_second":-1,"throttled_until":"","throttled_until_millis":0,"failures":[]}
return
}
//RefreshUser ... 刷新索引
func (t *User) RefreshUser() (err error) {
_, err = eSClient.Refresh().Index(t.TableName()).Do(context.TODO())
if err != nil {
fmt.Println("RefreshUser failed.", err)
return
}
return
}
//dsl=====================================
// CreateUser ... 单个创建
func (t *User) CreateUser() (user *User, err error) {
resp, err := eSClient.Index().
Index(t.TableName()).
Id(strconv.Itoa(int(t.Id))).
Refresh("true").
BodyJson(t).
Do(context.Background())
if err != nil {
fmt.Println("CreateUser err", err)
return
}
fmt.Printf("resp:%#v", resp)
userId, err := strconv.Atoi(resp.Id)
if err != nil {
fmt.Printf("CreateUser strconv.Atoi:%v err:%v", resp.Id, err)
return
}
t.Id = int64(userId)
user = t
return user, nil
}
// CreateBulkUsers ... 批量创建数据
func (t *User) CreateBulkUsers(list *[]User) (string, error) {
req := eSClient.Bulk().Index(t.TableName())
for _, item := range *list {
if item.Id != 0 {
//id := fmt.Sprintf("%s:%s", item.IP, item.Port)
fmt.Printf("正在导入ES数据索引:index:%s Id:%d \n", t.TableName(), item.Id)
doc := elastic.NewBulkIndexRequest().Id(strconv.Itoa(int(t.Id))).Doc(item)
req.Add(doc)
}
}
bulkResponse, err := req.Refresh("true").Do(context.Background())
if err != nil {
fmt.Printf("bulkResponse failed. errMsg:%v \n", err)
return "bulkResponse failed.", err
}
if bulkResponse == nil {
errMsg := fmt.Sprintf("expected bulkResponse to be != nil; got nil")
fmt.Println(errMsg)
err = errors.New(errMsg)
return "", err
}
if req.NumberOfActions() != 0 {
errMsg := fmt.Sprintf("CreateBulkUsers expected bulkRequest.NumberOfActions %d; got %d", 0, req.NumberOfActions())
fmt.Println(errMsg)
err := errors.New(errMsg)
return "", err
}
failed := bulkResponse.Failed()
bulkResponseFailedMarshal, _ := json.Marshal(failed)
fmt.Println("bulkResponseFailedMarshal:", string(bulkResponseFailedMarshal))
var success = make([]string, 0)
type failedDetail struct {
Ids []string
ErrorMagmap map[string]string
}
var fDetail failedDetail
fmt.Println("导入处理结果统计开始:============================================================>")
// 统计结果
for k, v := range bulkResponse.Items {
var item = *v["index"]
//global.Log.Infof("k:%#v , status:%#v err:%#v \n", k, v["index"].Status ,item.Error )
if v["index"].Status == 201 {
fmt.Printf("k--->:%#v , status:%#v id:%v err:%v v:%#v \n ", k, v["index"].Status, item.Id, item.Error, v["index"])
} else {
fmt.Printf("k:%#v , status:%#v id:%v err:%v \n", k, v["index"].Status, item.Id, item.Error)
}
if item.Error == nil {
success = append(success, item.Id)
} else {
fDetail.Ids = append(fDetail.Ids, item.Id)
b, _ := json.Marshal(item.Error)
fDetail.ErrorMagmap[item.Id] = string(b)
}
}
//fmt.Printf("success--->:%#v \n", success)
//fmt.Printf("fDetail--->:%#v \n", fDetail)
fmt.Println("导入处理结果结束:============================================================>")
responseMsg := fmt.Sprintf("总数: %d 条 , 成功: %d 条, 失败 %d 条.", len(*list), len(success), len(fDetail.Ids))
fmt.Println(responseMsg)
return responseMsg, nil
}
// RowExists 判断 users下的id=1的数据是否存在
func (t *User) RowExists(id string) bool {
exists, err := eSClient.Exists().Index(t.TableName()).Id(id).Do(context.TODO())
if err != nil {
fmt.Printf("err---->:%v \n", err)
return false
}
return exists
}
// GetUserInfo ... GET users/_doc/1 获取指定id的数据
func (t *User) GetUserInfo(_id string) (info User, err error) {
get, err := eSClient.Get().Index(t.TableName()).Id(_id).Do(context.Background())
if err != nil {
fmt.Println("GetUserInfo failed.", err)
return info, err
}
fmt.Printf("err:%v get:%#v \n", err, get)
if !get.Found {
return
}
//转为json格式
source, err := get.Source.MarshalJSON()
if err != nil {
fmt.Println("GetUserInfo get.Source.MarshalJSON() failed.", err)
return info, err
}
fmt.Printf("id:%s Source:%s \n", get.Id, string(source))
//转为struct格式
err = json.Unmarshal(source, &info)
if err != nil {
fmt.Println("json.Unmarshal GetUserInfo failed.", err)
return info, err
}
return info, err
}
// GetUserList ... 根据query条件筛选
/*
{
"query": {
"bool": {
"must": [
{
"term": {
"age": "31"
}
},
{
"term": {
"name.keyword": "wangermazhi"
}
},
{
"term": {
"height": "194.5"
}
},
{
"term": {
"id": "1651495760490"
}
}
],
"must_not": [],
"should": []
}
},
"from": 0,
"size": 10,
"sort": [
{
"created_at": {
"order": "desc"
}
}
]
}
*/
/*
{"bool":{"filter":{"range":{"age":{"from":31,"include_lower":true,"include_upper":true,"to":32}}},"must":[{"term":{"id":1651794923960}},{"term":{"name.keyword":"Lili"}},{"term":{"height":194.5}}]}}
{"bool":{"filter":{"ids":{"values":["1651794918330"]}},"must":[{"term":{"name.keyword":"maya"}},{"term":{"height":164.5}},{"term":{"age":32}}]}}
{"bool":{"filter":[{"ids":{"values":["1651794918330"]}},{"range":{"age":{"from":31,"include_lower":true,"include_upper":true,"to":32}}}],"must":[{"term":{"name.keyword":"maya"}},{"term":{"height":164.5}}]}}
https://www.cnblogs.com/you-men/p/13391265.html
*/
func (t *User) GetUserList(page, size int) (data []User, total int64, err error) {
query := elastic.NewBoolQuery()
if t.Id > 0 {
//query.Must(elastic.NewTermQuery("id", t.Id)) //query 按id查
ids := make([]string, 0)
ids = append(ids, fmt.Sprintf("%d", t.Id))
query.Filter(elastic.NewIdsQuery().Ids(ids...)) //filter 按ids查
}
if len(t.Name) > 0 {
query.Must(elastic.NewTermQuery("name.keyword", t.Name))
}
if t.Height > 0 {
query.Must(elastic.NewTermQuery("height", t.Height))
}
if t.Age > 0 {
//query.Must(elastic.NewTermQuery("age", t.Age)) //query 按age查
query.Filter(elastic.NewRangeQuery("age").Gte(31).Lte(32)) //filter 按age查
}
source, _ := query.Source()
marshalSource, _ := json.Marshal(source)
fmt.Println("GetUserDataList source:--->", string(marshalSource)) //打印query语句
includes := []string{"name","height","age"}
include := elasticCore.NewFetchSourceContext(true).Include(includes...)
sr, err := eSClient.Search(t.TableName()).
FetchSourceContext(include).
Query(query).
From((page-1)*size).
Size(size).
TrackTotalHits(true). //解除10000的限制
#SortBy(elasticCore.NewFieldSort("created_at").Desc(), elasticCore.NewScoreSort()).
Sort("created_at", false). //ture:asc false:desc 按照created_at升序排序, 无需排序则可跳过此设置, 多个Sort会按先后顺序依次生效
Pretty(true).
Do(context.Background())
if err != nil {
fmt.Printf("GetUserDataList.Search failed:%#v \n", err)
return
}
fmt.Printf("GetUserDataList Query took %d milliseconds\n", sr.TookInMillis) //GetUserAll Query took 0 milliseconds
if sr.Hits == nil {
errMsg := fmt.Sprintf("GetUserDataList expected Hits != nil; got: nil")
fmt.Printf("errMsg:%v err:%v \n", errMsg, err)
err = errors.New(errMsg)
return
}
//数据总数 hits.total.value里的值
total = sr.TotalHits()
fmt.Printf("total:%#v \n", total)
for _, item := range sr.Hits.Hits {
b, err := item.Source.MarshalJSON()
if err != nil {
fmt.Printf("item.Source.MarshalJSON() failed:%#v \n", err)
continue
}
var record User
err = json.Unmarshal(b, &record)
if err != nil {
fmt.Printf("json.Unmarshal record FofaData failed:%#v \n", err)
continue
}
data = append(data, record)
}
//fmt.Printf("err:%v total:%v data:%v", err, total, data)
return
}
// GetUserListAll ... 获取所有数据
/*
GET user/_search
{
"query": {
"bool": {
"must": [
{"match_all": {}}
]
}
}
, "from": 0
, "size": 2
, "sort": [
{
"created_at": {
"order": "desc"
}
}
]
}
*/
func (t *User) GetUserListAll(page, size int) (list []User, totalHits int64, err error) {
allQuery := elastic.NewMatchAllQuery()
//json query语句
source, _ := allQuery.Source()
marshalSource, _ := json.Marshal(source)
fmt.Println("allQuery:--->", string(marshalSource)) //打印query语句 allQuery:---> {"match_all":{}}
searchResult, err := eSClient.Search().
Index(t.TableName()).
Query(allQuery).
From((page-1)*size).
Size(size). //Size(不写默认为10)
TrackTotalHits(true). //解除10000的限制
Sort("created_at", false). //ture:asc false:desc 按照created_at升序排序, 无需排序则可跳过此设置, 多个Sort会按先后顺序依次生效
Pretty(true).
Do(context.Background())
if err != nil {
fmt.Println("GetUserAll failed.", err)
return
}
fmt.Printf("GetUserAll Query took %d milliseconds\n", searchResult.TookInMillis) //GetUserAll Query took 0 milliseconds
printUser(searchResult, err)
if searchResult.Hits == nil {
errMsg := fmt.Sprintf("expected Hits != nil; got: nil")
fmt.Printf("errMsg:%v err:%v \n", errMsg, err)
err = errors.New(errMsg)
return
}
//数据总数 hits.total.value里的值
totalHits = searchResult.TotalHits()
fmt.Printf("Found a total of %d user:\n", totalHits) //Found a total of 6 user:
//var ttyp User
//for _, item := range searchResult.Each(reflect.TypeOf(ttyp)) {
// it := item.(User)
// fmt.Printf("User by %s: %s\n",it.Name, it.Age)
//}
if searchResult.TotalHits() > 0 {
// Iterate through results
for _, hit := range searchResult.Hits.Hits {
// hit.Index contains the name of the index
// Deserialize hit.Source into a Tweet (could also be just a map[string]interface{}).
var user User
err := json.Unmarshal(hit.Source, &user)
if err != nil {
fmt.Printf("json.Unmarshal failed err:%v user:\n", err)
continue
}
// Work with tweet
//fmt.Printf("User by userId:%d: userName:%s created_at:%v\n", user.Id, user.Name, user.CreatedAt) //User by lisi: 32
fmt.Printf("User:%#v\n", user) //User by lisi: 32
list = append(list, user)
}
}
//判断否有聚合数据
//agg := searchResult.Aggregations
//if agg == nil {
// fmt.Printf("expected Aggregations != nil; got: nil \n")
// return
//}
return
}
// GetUserCount ... GET user/_count 获取文档里的总数据量
func (t *User) GetUserCount() (count int64) {
_ = t.RefreshUser()
count, err := eSClient.Count(t.TableName()).Do(context.TODO())
if err != nil {
fmt.Println("GetUserCount failed.", err)
return 0
}
return
}
// GetRowWithFilterAndAgg ... 获取OriginWeather索引里DestCountry = CN 聚合 OriginWeather 和 DestCityName
/*
{
"query": {
"bool":{
"filter":{
"term":{
"DestCountry":"CN"
}
}
}
},
"aggs": {
"agg_OriginWeather": {
"terms": {
"field":"OriginWeather",
"size": 10
}
},
"agg_DestCityName": {
"terms": {
"field":"DestCityName",
"size": 10
}
}
},
"size": 1
}
*/
func (t *User) GetRowWithFilterAndAgg() {
//聚合OriginWeather
aggs := elastic.NewTermsAggregation()
aggs.Field("OriginWeather")
aggs.Size(10)
source1, _ := aggs.Source()
marshalSource1, _ := json.Marshal(source1)
log.Println("marshalSource1:--->", string(marshalSource1)) //打印query语句
//marshalSource1:---> {"terms":{"field":"OriginWeather","size":10}}
//聚合DestCityName
aggs2 := elastic.NewTermsAggregation()
aggs2.Field("DestCityName")
aggs2.Size(10)
source2, _ := aggs2.Source()
marshalSource2, _ := json.Marshal(source2)
log.Println("marshalSource2:--->", string(marshalSource2)) //打印query语句
//marshalSource2:---> {"terms":{"field":"DestCityName","size":10}
//filter过滤 DestCountry = CN
query := elastic.NewBoolQuery()
query.Filter(elastic.NewTermQuery("DestCountry", "CN"))
source, _ := query.Source()
marshalSource, _ := json.Marshal(source)
log.Println("esQuery:--->", string(marshalSource)) //打印query语句
//esQuery:---> {"bool":{"filter":{"term":{"DestCountry":"CN"}}}}
res, err := eSClient.Search().
Size(1).
Index("kibana_sample_data_flights").
Query(query).
Aggregation("group_by_OriginWeather", aggs).
Aggregation("group_by_DestCityName", aggs2).
Do(context.Background())
if err != nil {
fmt.Printf("err---->:%v \n", err)
return
}
//log.Printf("res:--->%#v", res) //打印query语句
//获取Source
for _, item := range res.Hits.Hits {
b, err := item.Source.MarshalJSON()
if err != nil {
fmt.Printf("item.Source.MarshalJSON() failed:%#v \n", err)
continue
}
//打印Source
fmt.Println("b:--->", string(b))
// 解析 record
//var record Assets
//err = json.Unmarshal(b, &record)
//if err != nil {
// fmt.Printf("json.Unmarshal record Assets failed:%#v \n", err)
// continue
//}
//data = append(data, record)
}
//log.Println("res:--->", string(res)) //打印query语句
//fmt.Printf("id---->:%s Source:%s \n", res.Id, string(res))
var esdata []struct {
Name string `json:"key"`
Count int64 `json:"doc_count"`
}
// 获取 group_by_OriginWeather
term, _ := res.Aggregations.Terms("group_by_OriginWeather")
for _, bucket := range term.Aggregations {
b, _ := bucket.MarshalJSON()
_ = json.Unmarshal(b, &esdata)
}
for _, v := range esdata {
fmt.Println("v:--->", v)
}
// 获取 group_by_DestCityName
term2, _ := res.Aggregations.Terms("group_by_DestCityName")
for _, bucket := range term2.Aggregations {
b, _ := bucket.MarshalJSON()
_ = json.Unmarshal(b, &esdata)
}
for _, v := range esdata {
fmt.Println("v2:--->", v)
}
return
}
// GetMaxIdAgg ... 获取id的最大值
/*
POST user/_search
{
"aggs" : {
"max_id" : {
"max" : {
"field" : "id"
}
}
},
"size":1
}
*/
func (t *User) GetMaxIdAgg() (maxId float64, err error) {
all := elastic.NewMatchAllQuery()
builder := eSClient.Search().
Index(t.TableName()).
Query(all).
Size(1).
Pretty(true)
maxIdAgg := elastic.NewMaxAggregation().Field("id")
builder = builder.Aggregation("maxId", maxIdAgg)
searchResult, err := builder.Pretty(true).
Do(context.TODO())
if err != nil {
fmt.Println("GetMaxIdAgg builder.Pretty failed.", err)
return
}
if searchResult.Hits == nil {
errMsg := fmt.Sprintf("expected Hits != nil; got: nil")
fmt.Printf("err:%v \n", err)
err = errors.New(errMsg)
return
}
//totalHits := searchResult.TotalHits()
//fmt.Println("totalHits:", totalHits)
//if searchResult.TotalHits() != 1 {
// fmt.Printf("expected TotalHits() = %d; got: %d \n", 1, searchResult.TotalHits())
// return
//}
fmt.Println("searchResult.Hits.Hits:", searchResult.Hits.Hits)
if len(searchResult.Hits.Hits) != 1 {
errMsg := fmt.Sprintf("expected len(Hits.Hits) = %d; got: %d \n", 1, len(searchResult.Hits.Hits))
fmt.Printf("err:%v \n", err)
err = errors.New(errMsg)
return
}
agg := searchResult.Aggregations
if agg == nil {
errMsg := fmt.Sprintf("expected Aggregations != nil; got: nil \n")
fmt.Printf("err:%v \n", err)
err = errors.New(errMsg)
return
}
agg1, found := agg.Max("maxId")
if !found {
errMsg := fmt.Sprintf("expected %v; got: %v \n", true, found)
fmt.Printf("err:%v \n", err)
err = errors.New(errMsg)
return
}
if agg1 == nil {
errMsg := fmt.Sprintf("agg1 != nil; got: nil \n")
fmt.Printf("err:%v \n", err)
err = errors.New(errMsg)
return
}
if agg1.Value == nil {
errMsg := fmt.Sprintf("agg1.Value != nil; got: %v \n", *agg1.Value)
fmt.Printf("err:%v \n", err)
err = errors.New(errMsg)
return
}
//fmt.Printf("*agg1.Value %T",*agg1.Value)
maxId = *agg1.Value
return
}
//UpdateUserById ... 根据id新增或更新数据(单条) 仅更新传入的字段
/*
POST /test3/_update/1
{
"doc":{
"name":"fong"
}
}
*/
func (t *User) UpdateUserById(id string) (err error) {
update := map[string]interface{}{}
if t.Name != "" {
update["name"] = t.Name
}
if t.Height != 0 {
update["height"] = t.Height
}
if t.Age != 0 {
update["age"] = t.Age
}
update["updated_at"] = carbon.Now().ToDateTimeString()
res, err := eSClient.Update().
Index(t.TableName()).
Id(id).
Refresh("true").
// update为结构体或map, 需注意的是如果使用结构体零值也会去更新原记录
Upsert(update).
// true 无则插入, 有则更新, 设置为false时记录不存在将报错
DocAsUpsert(true).
Do(context.Background())
if err != nil {
println(err.Error())
}
fmt.Printf("update age %s %#v \n", res.Result, res)
return
}
// DeleteUserById 指定id删除数据 DELETE /user/_doc/2
func (t *User) DeleteUserById(_id string) (err error) {
deleteResult, err := eSClient.Delete().Index(t.TableName()).Id(_id).Refresh("true").Do(context.Background())
// Delete document again
//deleteResult, err := eSClient.Delete().Index(t.TableName()).Id(id).Do(context.TODO())
if err != nil {
fmt.Println("DeleteUserById failed.", err)
return
}
if deleteResult == nil {
errMsg := fmt.Sprintf("expected result to be != nil; got: %v", deleteResult)
fmt.Printf("err:%v \n", err)
err = errors.New(errMsg)
return err
}
// Exists
exists, err := eSClient.Exists().Index(t.TableName()).Id(_id).Do(context.TODO())
if err != nil {
fmt.Println("DeleteUserById eSClient.Exists() failed.", err)
return
}
if exists {
errMsg := fmt.Sprintf("expected exists %v; got %v \n", false, exists)
fmt.Printf("err:%v \n", err)
err = errors.New(errMsg)
return err
}
return nil
}
// DeleteUserByQuery 按Query条件删除
/*
https://blog.csdn.net/u013200380/article/details/109163812
POST user/_delete_by_query?scroll_size=5000
{
"query":{
"bool":{
"must":[
{
"term":{
"age":"31"
}
},
{
"term":{
"name.keyword":"wangermazhi"
}
}
]
}
}
}
*/
/*
JSON响应类似如下:
{
"took" : 147,
"timed_out": false,
"total": 119,
"deleted": 119,
"batches": 1,
"version_conflicts": 0,
"noops": 0,
"retries": {
"bulk": 0,
"search": 0
},
"throttled_millis": 0,
"requests_per_second": -1.0,
"throttled_until_millis": 0,
"failures" : [ ]
}
took: 从整个操作的开始到结束的毫秒数。
timed_out: delete by query的请求处理过程中是否超时
total: 成功处理的doc数量
deleted: 成功删除的文档数。
batches: 通过查询删除的scroll响应数量。
version_conflicts: 根据查询删除时,版本冲突的数量。
noops: 这个在这里没有用,只是为了让delete by query, update by query, and reindex APIs 返回相同结构的 responses
retries: search 操作和bulk操作的重试次数
throttled_millis: 因为requests_per_second而产生的睡眠时间
requests_per_second: 每秒处理的请求数
throttled_until_millis: 这个也是总是0,没有用,为了保持结构一致性
failures: 失败的情况,会终止操作的失败
*/
func (t *User) DeleteUserByQuery() (err error) {
query := elastic.NewBoolQuery()
if t.Id > 0 {
query.Must(elastic.NewTermQuery("id", t.Id))
}
if len(t.Name) > 0 {
query.Must(elastic.NewTermQuery("name.keyword", t.Name))
}
source, _ := query.Source()
marshalSource, _ := json.Marshal(source)
fmt.Println("DeleteUserByQuery:--->", string(marshalSource)) //打印query语句
//DeleteUserByQuery:---> {"bool":{"must":[{"term":{"id.keyword":1651536087022}},{"term":{"name.keyword":"Lili"}}]}}
resp, err := eSClient.DeleteByQuery().
Index(t.TableName()).
Query(query).
ScrollSize(5000). //默认情况下_delete_by_query使用滚动批量处理数量为1000。您可以使用URL的scroll_size参数更改批量大小:
Slices("auto").
Pretty(true).
Refresh("true").
Do(context.TODO())
//DoAsync(context.TODO())
if err != nil {
fmt.Printf("DeleteUserByQuery failed:%#v \n", err)
return
}
if resp == nil {
errMsg := fmt.Sprintf("expected result != nil \n")
fmt.Printf("err:%v \n", err)
err = errors.New(errMsg)
return err
}
//if resp.TaskId == "" {
// errMsg := fmt.Sprintf("expected a task id, got %+v \n", resp)
// fmt.Printf("err:%v \n", err)
// err = errors.New(errMsg)
// return err
//}
fmt.Printf("err:%v resp:%#v \n", err, resp)
//tasksGetTask := eSClient.TasksGetTask()
//taskStatus, err := tasksGetTask.TaskId(resp.TaskId).Do(context.TODO())
//if err != nil {
// errMsg := fmt.Sprintf("tasksGetTask.TaskId failed err:%+v \n", err)
// fmt.Printf("err:%v \n", err)
// err = errors.New(errMsg)
// return err
//}
//if taskStatus == nil {
// err = errors.New("expected task status result != nil")
// fmt.Printf("err:%v \n", err)
// return err
//}
return
}
// DeleteAllUser ... 删除user索引所有的数据
/*
POST user/_delete_by_query?scroll_size=5000
{
"query":{ "match_all": {}}
}
*/
func (t *User) DeleteAllUser() (err error) {
allQuery := elastic.NewMatchAllQuery()
//json query语句
source, _ := allQuery.Source()
marshalSource, _ := json.Marshal(source)
fmt.Println("allQuery:--->", string(marshalSource)) //打印query语句 allQuery:---> {"match_all":{}}
resp, err := eSClient.DeleteByQuery().
Index("user_test").
Query(allQuery).
ScrollSize(5000). //默认情况下_delete_by_query使用滚动批量处理数量为1000。您可以使用URL的scroll_size参数更改批量大小:
Slices("auto").
Pretty(true).
Refresh("true").
Do(context.TODO())
if err != nil {
fmt.Printf("DeleteUserAll failed:%#v \n", err)
return
}
if resp == nil {
errMsg := fmt.Sprintf("expected result != nil \n")
fmt.Printf("err:%v \n", err)
err = errors.New(errMsg)
return err
}
return
}
//打印查询到的User
func printUser(res *elastic.SearchResult, err error) {
if err != nil {
print(err.Error())
return
}
var typ User
for _, item := range res.Each(reflect.TypeOf(typ)) { //从搜索结果中取数据的方法
t := item.(User)
fmt.Printf("--->:%#v %#v\n", t.Id, t.Name)
fmt.Printf("--->:%#v\n", t)
}
}
测试用例
user_test.go
package model
import (
"fmt"
"github.com/golang-module/carbon/v2"
"reflect"
"testing"
)
//mapping=====================================
//IndexExists 判断IndexExists是否存在
func TestUser_IndexExists(t1 *testing.T) {
var user User
exists, err := user.IndexExists()
fmt.Println("exists:", exists)
fmt.Println("err:", err)
}
//DeleteIndex 删除索引
func TestUser_DeleteIndex(t1 *testing.T) {
var user User
isBool, err := user.DeleteIndex()
fmt.Println("isBool:", isBool)
fmt.Println("err:", err)
}
// AddIndexField ... 更新索引 仅支持添加字段, 已有字段无法修改
func TestUser_AddIndexField(t1 *testing.T) {
var user User
isBool, err := user.AddIndexField()
fmt.Println("isBool:", isBool)
fmt.Println("err:", err)
}
// CreateIndexWithSettings ... 创建索引 设置分片数
func TestUser_CreateIndexWithSettings(t1 *testing.T) {
type fields struct {
Id int64
Name string
Height float32
Age int8
State bool
CreatedAt string
UpdatedAt string
}
tests := []struct {
name string
fields fields
want bool
wantErr bool
}{
// TODO: Add test cases.
{
name: "CreateIndexWithSettings",
want: true,
wantErr: false,
},
}
for _, tt := range tests {
t1.Run(tt.name, func(t1 *testing.T) {
t := &User{
Id: tt.fields.Id,
Name: tt.fields.Name,
Height: tt.fields.Height,
Age: tt.fields.Age,
State: tt.fields.State,
CreatedAt: tt.fields.CreatedAt,
UpdatedAt: tt.fields.UpdatedAt,
}
got, err := t.CreateIndexWithSettings()
fmt.Println("got:", got)
if (err != nil) != tt.wantErr {
t1.Errorf("CreateIndexWithSettings() error = %v, wantErr %v", err, tt.wantErr)
return
}
if got != tt.want {
t1.Errorf("CreateIndexWithSettings() got = %v, want %v", got, tt.want)
}
})
}
}
// GetMapping Mapping. 获取mapping
func TestUser_GetMapping(t1 *testing.T) {
var user User
mappingString, err := user.GetMapping()
fmt.Println("mappingString:", mappingString)
fmt.Println("err:", err)
}
// // Reindex ... 数据迁移 将一个索引的数据迁移到另一个索引中, 一般用于索引结构发生改变时使用新索引存储数据
func TestUser_Reindex(t1 *testing.T) {
type fields struct {
Id int64
Name string
Height float32
Age int8
State bool
CreatedAt string
UpdatedAt string
}
tests := []struct {
name string
fields fields
wantErr bool
}{
// TODO: Add test cases.
{
name: "Reindex",
wantErr: false,
},
}
for _, tt := range tests {
t1.Run(tt.name, func(t1 *testing.T) {
t := &User{
Id: tt.fields.Id,
Name: tt.fields.Name,
Height: tt.fields.Height,
Age: tt.fields.Age,
State: tt.fields.State,
CreatedAt: tt.fields.CreatedAt,
UpdatedAt: tt.fields.UpdatedAt,
}
if err := t.Reindex(); (err != nil) != tt.wantErr {
t1.Errorf("Reindex() error = %v, wantErr %v", err, tt.wantErr)
}
})
}
}
//RefreshUser ... 刷新索引
func TestUser_RefreshUser(t1 *testing.T) {
type fields struct {
Id int64
Name string
Height float32
Age int8
State bool
CreatedAt string
UpdatedAt string
}
tests := []struct {
name string
fields fields
wantErr bool
}{
// TODO: Add test cases.
{
name: "RefreshUser",
wantErr: false,
},
}
for _, tt := range tests {
t1.Run(tt.name, func(t1 *testing.T) {
t := &User{
Id: tt.fields.Id,
Name: tt.fields.Name,
Height: tt.fields.Height,
Age: tt.fields.Age,
State: tt.fields.State,
CreatedAt: tt.fields.CreatedAt,
UpdatedAt: tt.fields.UpdatedAt,
}
if err := t.RefreshUser(); (err != nil) != tt.wantErr {
t1.Errorf("RefreshUser() error = %v, wantErr %v", err, tt.wantErr)
}
})
}
}
//dsl=====================================
// RowExists 判断 users下的id=1的数据是否存在
func TestUser_RowExists(t1 *testing.T) {
var user User
rowExists := user.RowExists("1651536057224")
fmt.Println("rowExists:", rowExists)
}
//createUser ... 单个创建
func TestUser_createUser(t1 *testing.T) {
type fields struct {
Id int64
Name string
Height float32
Age int8
State bool
CreatedAt string
UpdatedAt string
}
tests := []struct {
name string
fields fields
wantErr bool
}{
// TODO: Add test cases.
{
name: "createUser01",
fields: fields{
Id: carbon.Now().TimestampMilli(),
Name: "maya",
Height: 164.5,
Age: 32,
State: true,
CreatedAt: carbon.Now().ToDateTimeString(),
UpdatedAt: carbon.Now().ToDateTimeString(),
},
},
{
name: "createUser02",
fields: fields{
Id: carbon.Now().TimestampMilli(),
Name: "Lili",
Height: 194.5,
Age: 31,
State: true,
CreatedAt: carbon.Now().ToDateTimeString(),
UpdatedAt: carbon.Now().ToDateTimeString(),
},
wantErr: false,
},
}
for _, tt := range tests {
t1.Run(tt.name, func(t1 *testing.T) {
t := &User{
Id: tt.fields.Id,
Name: tt.fields.Name,
Height: tt.fields.Height,
Age: tt.fields.Age,
State: tt.fields.State,
CreatedAt: tt.fields.CreatedAt,
UpdatedAt: tt.fields.UpdatedAt,
}
userInfo, err := t.CreateUser()
fmt.Println("err:", err)
fmt.Println("userInfo.Id:", userInfo.Id)
fmt.Println("userInfo:", userInfo)
if (err != nil) != tt.wantErr {
t1.Errorf("createUser() error = %v, wantErr %v", err, tt.wantErr)
}
})
}
}
// CreateBulkUsers ... 批量创建数据
func TestUser_CreateBulkUsers(t1 *testing.T) {
type fields struct {
Id int64
Name string
Height float32
Age int8
State bool
CreatedAt string
UpdatedAt string
}
type args struct {
list *[]User
}
var user1 = User{
Id: carbon.Now().TimestampWithMicrosecond(),
Name: "shanpao",
Height: 164.5,
Age: 31,
State: true,
CreatedAt: carbon.Now().ToDateTimeString(),
UpdatedAt: carbon.Now().ToDateTimeString(),
}
var user2 = User{
Id: carbon.Now().TimestampWithMicrosecond(),
Name: "Jim",
Height: 164.5,
Age: 30,
State: true,
CreatedAt: carbon.Now().ToDateTimeString(),
UpdatedAt: carbon.Now().ToDateTimeString(),
}
tests := []struct {
name string
fields fields
args args
want string
wantErr bool
}{
// TODO: Add test cases.
{
name: "CreateBulkUsers",
args: args{list: &[]User{user1, user2}},
wantErr: false,
},
}
for _, tt := range tests {
t1.Run(tt.name, func(t1 *testing.T) {
t := &User{
Id: tt.fields.Id,
Name: tt.fields.Name,
Height: tt.fields.Height,
Age: tt.fields.Age,
State: tt.fields.State,
CreatedAt: tt.fields.CreatedAt,
UpdatedAt: tt.fields.UpdatedAt,
}
got, err := t.CreateBulkUsers(tt.args.list)
fmt.Println("got:", got)
fmt.Println("err:", err)
if (err != nil) != tt.wantErr {
t1.Errorf("CreateBulkUsers() error = %v, wantErr %v", err, tt.wantErr)
return
}
//if got != tt.want {
// t1.Errorf("CreateBulkUsers() got = %v, want %v", got, tt.want)
//}
})
}
}
// GetUserInfo ... GET users/_doc/1 获取指定id的数据
func TestUser_GetUserInfo(t1 *testing.T) {
type fields struct {
Id int64
Name string
Height float32
Age int8
State bool
CreatedAt string
UpdatedAt string
}
type args struct {
id string
}
tests := []struct {
name string
fields fields
args args
wantInfo User
wantErr bool
}{
// TODO: Add test cases.
{
name: "GetUserInfo",
args: args{
id: "1651794918330",
},
fields: fields{
Id: 1651495760490,
},
wantInfo: User{
Id: 1651495760490,
},
wantErr: false,
},
}
for _, tt := range tests {
t1.Run(tt.name, func(t1 *testing.T) {
t := &User{
Id: tt.fields.Id,
Name: tt.fields.Name,
Height: tt.fields.Height,
Age: tt.fields.Age,
State: tt.fields.State,
CreatedAt: tt.fields.CreatedAt,
UpdatedAt: tt.fields.UpdatedAt,
}
gotInfo, err := t.GetUserInfo(tt.args.id)
fmt.Println("gotInfo:", gotInfo)
if (err != nil) != tt.wantErr {
t1.Errorf("GetUserInfo() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !reflect.DeepEqual(gotInfo.Id, tt.wantInfo.Id) {
t1.Errorf("GetUserInfo() gotInfo = %v, want %v", gotInfo.Id, tt.wantInfo.Id)
}
})
}
}
// GetUserDataList ... 根据query条件筛选
func TestUser_GetUserList(t1 *testing.T) {
type fields struct {
Id int64
Name string
Height float32
Age int8
State bool
CreatedAt string
UpdatedAt string
}
type args struct {
page int
size int
}
tests := []struct {
name string
fields fields
args args
wantData []User
wantTotal int64
wantErr bool
}{
// TODO: Add test cases.
{
name: "GetUserDataList",
fields: fields{
Id: 1651794918330,
Name: "maya",
Age: 32,
Height: 164.5,
},
args: args{
page: 1, size: 10,
},
wantErr: false,
},
}
for _, tt := range tests {
t1.Run(tt.name, func(t1 *testing.T) {
t := &User{
Id: tt.fields.Id,
Name: tt.fields.Name,
Height: tt.fields.Height,
Age: tt.fields.Age,
State: tt.fields.State,
CreatedAt: tt.fields.CreatedAt,
UpdatedAt: tt.fields.UpdatedAt,
}
gotData, gotTotal, err := t.GetUserList(tt.args.page, tt.args.size)
fmt.Println("gotData:", gotData)
fmt.Println("gotTotal:", gotTotal)
if (err != nil) != tt.wantErr {
t1.Errorf("GetUserDataList() error = %v, wantErr %v", err, tt.wantErr)
return
}
//if !reflect.DeepEqual(gotData, tt.wantData) {
// t1.Errorf("GetUserDataList() gotData = %v, want %v", gotData, tt.wantData)
//}
//if gotTotal != tt.wantTotal {
// t1.Errorf("GetUserDataList() gotTotal = %v, want %v", gotTotal, tt.wantTotal)
//}
})
}
}
// GetUserListAll ... 获取所有数据
func TestUser_GetUserListAll(t1 *testing.T) {
type fields struct {
Id int64
Name string
Height float32
Age int8
State bool
CreatedAt string
UpdatedAt string
}
tests := []struct {
name string
fields fields
wantList []User
wantErr bool
}{
// TODO: Add test cases.
{
name: "GetUserListAll",
wantErr: false,
},
}
for _, tt := range tests {
t1.Run(tt.name, func(t1 *testing.T) {
t := &User{
Id: tt.fields.Id,
Name: tt.fields.Name,
Height: tt.fields.Height,
Age: tt.fields.Age,
State: tt.fields.State,
CreatedAt: tt.fields.CreatedAt,
UpdatedAt: tt.fields.UpdatedAt,
}
gotList, totalHits, err := t.GetUserListAll(1, 2)
if (err != nil) != tt.wantErr {
t1.Errorf("GetUserListAll() error = %v, wantErr %v", err, tt.wantErr)
return
}
fmt.Println("totalHits:", totalHits)
fmt.Printf("gotListLen:%d gotList:%v", len(gotList), gotList)
//if !reflect.DeepEqual(gotList, tt.wantList) {
// t1.Errorf("GetUserListAll() gotList = %v, want %v", gotList, tt.wantList)
//}
})
}
}
// GetMaxIdAgg
func TestUser_GetMaxIdAgg(t1 *testing.T) {
var user User
maxId, err := user.GetMaxIdAgg()
fmt.Println("err:", err)
fmt.Printf("type:%T maxId:%v\n", maxId, maxId)
}
//DeleteUserById 指定id删除数据
func TestUser_DeleteUserById(t1 *testing.T) {
type fields struct {
Id int64
Name string
Height float32
Age int8
State bool
CreatedAt string
UpdatedAt string
}
type args struct {
_id string
}
tests := []struct {
name string
fields fields
args args
wantErr bool
}{
// TODO: Add test cases.
{
name: "DeleteUserById",
args: args{_id: "1651536057224"},
},
}
for _, tt := range tests {
t1.Run(tt.name, func(t1 *testing.T) {
t := &User{
Id: tt.fields.Id,
Name: tt.fields.Name,
Height: tt.fields.Height,
Age: tt.fields.Age,
State: tt.fields.State,
CreatedAt: tt.fields.CreatedAt,
UpdatedAt: tt.fields.UpdatedAt,
}
if err := t.DeleteUserById(tt.args._id); (err != nil) != tt.wantErr {
t1.Errorf("DeleteUserById() error = %v, wantErr %v", err, tt.wantErr)
}
})
}
}
// GetUserCount ... 获取文档里的总数据量
func TestUser_GetUserCount(t1 *testing.T) {
type fields struct {
Id int64
Name string
Height float32
Age int8
State bool
CreatedAt string
UpdatedAt string
}
tests := []struct {
name string
fields fields
wantCount int64
}{
// TODO: Add test cases.
{
name: "GetUserCount",
},
}
for _, tt := range tests {
t1.Run(tt.name, func(t1 *testing.T) {
t := &User{
Id: tt.fields.Id,
Name: tt.fields.Name,
Height: tt.fields.Height,
Age: tt.fields.Age,
State: tt.fields.State,
CreatedAt: tt.fields.CreatedAt,
UpdatedAt: tt.fields.UpdatedAt,
}
gotCount := t.GetUserCount()
fmt.Println("gotCount:", gotCount)
//if gotCount != tt.wantCount {
// t1.Errorf("GetUserCount() = %v, want %v", gotCount, tt.wantCount)
//}
})
}
}
// DeleteUserByQuery 按Query条件删除
func TestUser_DeleteUserByQuery(t1 *testing.T) {
type fields struct {
Id int64
Name string
Height float32
Age int8
State bool
CreatedAt string
UpdatedAt string
}
tests := []struct {
name string
fields fields
wantErr bool
}{
// TODO: Add test cases.
{
name: "DeleteUserByQuery",
fields: fields{
Id: 1651536050639,
Name: "Tom",
},
wantErr: false,
},
{
name: "DeleteUserByQuery",
fields: fields{
Id: 1651536002084,
Name: "job",
},
wantErr: false,
},
}
for _, tt := range tests {
t1.Run(tt.name, func(t1 *testing.T) {
t := &User{
Id: tt.fields.Id,
Name: tt.fields.Name,
Height: tt.fields.Height,
Age: tt.fields.Age,
State: tt.fields.State,
CreatedAt: tt.fields.CreatedAt,
UpdatedAt: tt.fields.UpdatedAt,
}
if err := t.DeleteUserByQuery(); (err != nil) != tt.wantErr {
t1.Errorf("DeleteUserByQuery() error = %v, wantErr %v", err, tt.wantErr)
}
})
}
}
//DeleteUserAll ... 删除user索引所有的数据
func TestUser_DeleteUserAll(t1 *testing.T) {
type fields struct {
Id int64
Name string
Height float32
Age int8
State bool
CreatedAt string
UpdatedAt string
}
tests := []struct {
name string
fields fields
wantErr bool
}{
// TODO: Add test cases.
{
name: "DeleteAllUser",
wantErr: false,
},
}
for _, tt := range tests {
t1.Run(tt.name, func(t1 *testing.T) {
t := &User{
Id: tt.fields.Id,
Name: tt.fields.Name,
Height: tt.fields.Height,
Age: tt.fields.Age,
State: tt.fields.State,
CreatedAt: tt.fields.CreatedAt,
UpdatedAt: tt.fields.UpdatedAt,
}
if err := t.DeleteAllUser(); (err != nil) != tt.wantErr {
t1.Errorf("DeleteUserAll() error = %v, wantErr %v", err, tt.wantErr)
}
})
}
}
作者:海马 创建时间:2023-07-02 11:33
最后编辑:海马 更新时间:2025-01-27 10:55
最后编辑:海马 更新时间:2025-01-27 10:55