golang *** 作 elasticsearch

golang  *** 作 elasticsearch,第1张

在网上看了一些,具体的有两种,一种是 github.com/olivere/elastic *** 作,还有一种用的是 github.com/elastic/go-elasticsearch ,后一中好像用的少,但是不巧的是我用的就是后一种。

        查询的条件语句很好拼,但是不会在golang中用,在golang中 *** 作的基本上都是用map[string]interface{}拼接然后转json,类似于这种:

query := map[string]interface{}{
		"query": map[string]interface{}{
			"bool": map[string]interface{}{
				"filter": map[string]interface{}{
					"multi_match": map[string]interface{}{
						"query":  key.KeyWord,
						"fields": []string{"produceCompany", "productName"},
					},
				},
			},
		},
	}

	body, _ := json.Marshal(&query)

作为小白,那就找到啥用啥,但是有个问题,就是我的es语句是带有 “[ ]”的,没办法用map[string]interface{},为此我还苦恼了两三天找不到怎么在interface{}中加[ ]的办法。然后有一位新来的大佬说,既然都是转json,那就用结构体转吧。然后,问题就解决了。idea有自带的json转struct,可以直接复制json语句粘贴,自己就转了。非常好用

然后就是查找,根据条件拼接es语句,拼起来转为json,实现查找

func (s *SearchService) GetCollection(ctx context.Context, key *request.CollectionReq) (interface{}, error) {
	//各个条件判断
    var filter []interface{}
	if key.CollectionType != 0 {
		var auto search.AutoCollectionType
		auto.Bool.Must.Match.CollectionType = key.CollectionType
		filter = append(filter, auto)
	}
	if key.ProductCategory != 0 {
		var auto search.AutoProductCategory
		auto.Bool.Must.Match.ProductCategory = key.ProductCategory
		filter = append(filter, auto)
	}
	if key.ProvinceCode != "" {
		var auto search.AutoProvinceCode
		auto.Bool.Must.Match.ProvinceCode = key.ProvinceCode
		filter = append(filter, auto)
	}
	if key.CityCode != "" {
		var auto search.AutoCityCode
		auto.Bool.Must.Match.CityCode = key.CityCode
		filter = append(filter, auto)
	}
	if key.TerminalType != "" {
		var auto search.AutoTerminalType
		auto.Bool.Must.Match.TerminalType = key.TerminalType
		filter = append(filter, auto)
	}
	if key.CreatedAtStart != "" {
		var auto search.AutoCreate
		auto.Bool.Must.Range.CreatedAt.Gte = key.CreatedAtStart
		auto.Bool.Must.Range.CreatedAt.Lte = key.CreatedAtEnd
		filter = append(filter, auto)
	}
	if key.KeyWord != "" {
		var auto search.AutoKeyWord
		auto.Bool.Must.MultiMatch.Fields = []string{"produceCompany", "productName", "title", "terminalName"}
		auto.Bool.Must.MultiMatch.Query = key.KeyWord
		filter = append(filter, auto)
	}
    //获取查询的query
	query := search.EsQuery{
		Query: struct {
			Bool struct {
				Filter []interface{} `json:"filter"`
			} `json:"bool"`
		}{},
	}
	query.Query.Bool.Filter = filter
    //转json
	body, _ := json.Marshal(&query)
	req := esapi.SearchRequest{
		Index:        []string{CollSchemaName}, //es对应的_index
		DocumentType: []string{CollSchemaName}, //es对应的_type   
		Body:         bytes.NewReader(body),    //查询的结构体
		Size:         &key.PageSize,            //分页    
		From:         &key.Page,                
		Source:       []string{"id"},           //只查id
	}
	res, err := req.Do(ctx, s.Client)  //s.Client是 elasticsearch.Client的
	if err != nil {
		global.GVA_LOG.Error(err.Error())
	}
	if res.StatusCode > 300 {
		global.GVA_LOG.Error("es 查询错误,错误信息:" + res.String())
		return nil, err
	}
	//查询结果res,类型为io.ReadCloser,转为json
	buff := new(bytes.Buffer)
	_, err = buff.ReadFrom(res.Body)
	if err != nil {
		return nil, err
	}
	buffBytes := buff.Bytes()
	//json 转 struct
	buffJson := response.CollectionRespElastic{}
	_ = json.Unmarshal(buffBytes, &buffJson)
	var ids []string
	for _, val := range buffJson.Hits.Hits {
		ids = append(ids, val.Id)
	}

	defer res.Body.Close()
    //数据库查找(因为es库存的是搜索的关键信息,所以最后还是要从mysql查)
	if key.CollectionType == 1 {
		var list []*respBusiness.CollectionDetailResp
		err = global.GVA_DB.Table("v_collection_detail").Where("id in ?", ids).Find(&list).Error
		return list, err
	} else if key.CollectionType == 2 {
		var list []*respBusiness.CollResp
		err = global.GVA_DB.Model(&respBusiness.CollResp{}).Where("id in ?", ids).Find(&list).Error
		return list, err
	}
	return nil, err
}

        从es查出来的数据也是同样的map[string]interface{}的结构,查出来的东西都在hits[ ]中,之前钻牛角尖,妄图在map[string]interface{}中把hits[ ] 取出来,转念一想,还是用struct方便

{
  "took": 0,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": 80,
    "max_score": 1.0,
    "hits": []
  }
}

        一样的思路,用结构体接收,用不到的就直接interface{},用到的就定义,json一定要对应好,定义之后取用就很方便

type CollectionRespElastic struct {
	Took     int         `json:"took"`
	TimedOut bool        `json:"timed_out"`
	Shards   interface{} `json:"_shards"`
	Hits     *Hits       `json:"hits"`
}

type Hits struct {
	Total    int      `json:"total"`
	MaxScore int      `json:"max_score"`
	Hits     []*Hitss `json:"hits"`
}

type Hitss struct {
	Index  string      `json:"_index"`
	Type   string      `json:"_type"`
	Id     string      `json:"_id"`
	Soure  int         `json:"_score"`
	Source interface{} `json:"_source"`
}

有个小问题,就是es 查询不支持查“空”字段,比如collectionMode字段类型是text,但是没有存数据,查看全部显示的是  " " ,但是如果你在查询条件中写{ "collectionMode":" " }这样就会报错

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/995035.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-21
下一篇 2022-05-21

发表评论

登录后才能评论

评论列表(0条)

保存