1. 主要针对普通查询方式的简单封装,查询语句类似于

{
"query": {
"bool": {
"should": [
{
"multi_match": {
"query": "爱情",
"fields": ["tags", "categories"],
"type": "phrase"
}
},
{
"multi_match": {
"query": "古装",
"fields": ["tags", "categories"],
"type": "phrase"
}
}
]
}
},
"size": 10
}

2. 返回格式类似于:

{
"took": 20,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 5785,
"relation": "eq"
},
"max_score": 7.9,
"hits": [
{
"_index": "video",
"_id": "1529",
"_score": 7.911426,
"_source": {
"id": 7755,
"title": "蜀山封魔传",
"sub_title": "周路 毛娜 楼南光",
"third_title": "仙侠玄幻",
"third_title_type": 80,
"release_at": "2024-08-31",
"year": 2024,
"video_language": "普通话",
"brief": "主角廖不凡在世人眼中,是个谁见谁倒霉的扫把星。为了改变命运,他到蜀山拜师修行,最终得到他人的认同与帮助,实现了自我价值与理想。廖不凡不是个幽默的人,但他经常以一副嬉皮笑脸的面容面对世界,但是有时候他是以笑容掩饰内心的焦虑,不让别人为他担心。对于外人而言,他是个随遇而安的人,但身边的人往往能看出他埋藏在心中的忧虑,看似莽撞的他同时也很理智,明白正确的道路不是一条轻松的路,行走在这条路上将会遭遇无数艰难险阻。女主角玲珑拒绝道听途说相信亲眼所见,正是她的爱意才让廖更加相信自己的选择,没有背道而驰。",
"cover_h": "https://www.video.com/cover_h/7755",
"cover_v": "https://www.video.com/cover_v/7755",
"country": "内地",
"total_episodes": 1,
"last_episodes": "全1集",
"is_end": 1,
"ranking": "",
"vip": 0,
"playpoint": 0,
"total_views": 5825,
"total_score": 61,
"channel": "电影",
"categories": [
"动作",
"喜剧",
"爱情",
"古装",
"奇幻",
"玄幻"
],
"category_id": [
1,
2,
3,
4,
5,
6
],
"tags": [
"玄幻",
"内地",
"搞笑",
"原创",
"古装",
"爱情",
"小人物",
"喜剧",
"仙侠"
],
"actors": [
"锦泷",
"毛娜",
"楼南光",
"邵琨"
],
"directors": [
"陈玉勇"
],
"updated_at": "2024-10-07 19:59:41",
"created_at": "2024-10-07 10:57:18",
"channel_id": 99
}
}
]
}
}


3. 定义 es 的基础数据结构, 目录结果为 esmodels/EsQueryRes.go

package esmodels
import "encoding/json"
// es 原始请求结果定义
// es 查询请求 map
type EsSearchMap map[string]interface{}
type EsSearchArray []EsSearchMap
// type EsSearchResponseMap map[string]interface{}
// es 查询的 hits 数组中的一个结构
type EsSearchHitsBase struct {
Index string `json:"_index"`
Id string `json:"_id"`
Score float64 `json:"_score"`
}
// es 查询的 hits 数组中的一个结构
type EsSearchHitsSource struct {
EsSearchHitsBase
Source json.RawMessage `json:"_source"`
Highlight json.RawMessage `json:"highlight"`
}
// es 查询的 hits 中的 total
type EsSearchHitsTotal struct {
Value int64 `json:"value"`
Relation string `json:"relation"`
}
// es 查询的 hits
type EsSearchHits struct {
Total EsSearchHitsTotal `json:"total"`
Hits []*EsSearchHitsSource `json:"hits"`
MaxScore float64 `json:"max_score"`
}
type EsSearchSimple struct {
Hits EsSearchHits `json:"hits"`
Aggregations EsAggregations `json:"aggregations"`
}


4. 封装的 golang 代码示例,会用到 github.com/elastic/go-elasticsearch/v8 库

package function
import (
"bytes"
"context"
"encoding/json"
"fmt"
"project/models/esmodels"
"strings"
"github.com/elastic/go-elasticsearch/v8"
"github.com/elastic/go-elasticsearch/v8/esapi"
)
// 与业务逻辑无关的公共 es 方法
// 简单查询
func EsSimpleSearch(es *elasticsearch.Client,query esmodels.EsSearchMap, index []string, pretty bool) (queryRes *esmodels.EsSearchSimple, err error) {
// 将查询 DSL 转换为 JSON
if IsTestEnv() {
var queryBytes []byte
queryBytes, err = json.Marshal(query)
if err != nil {
return
}
queryString := string(queryBytes)
logs.Debug("EsSimpleSearch -- qurey: %v", queryString)
}
var buf bytes.Buffer
if err = json.NewEncoder(&buf).Encode(query); err != nil {
err = fmt.Errorf("es transform query to json fail, err:%v", err)
return
}
req := esapi.SearchRequest{
Index: index, // 索引名
Body: &buf,
Pretty: pretty, // 格式化输出
}
res, err := req.Do(context.Background(), es)
if err != nil {
err = fmt.Errorf("es request search fail, err:%v", err)
return
}
defer res.Body.Close()
if res.IsError() {
err = fmt.Errorf("es search response fail, err:%v", err)
return
}
logs.Debug("EsSimpleSearch, query: %v, response:%v", query, res.Body)
// Parse the response
queryRes = &esmodels.EsSearchSimple{}
// queryRes := EsSearchMap{}
if err = json.NewDecoder(res.Body).Decode(&queryRes); err != nil {
err = fmt.Errorf("es search decode fail, err:%v", err)
return
}
if IsTestEnv() {
var queryBytes []byte
queryBytes, err = json.Marshal(queryRes)
if err != nil {
return
}
queryString := string(queryBytes)
logs.Debug("EsSimpleSearch -- response: %v", queryString)
}
return
}


5.使用示例

query := esmodels.EsSearchMap{
"query": esmodels.EsQuery{
"match_all": nil,
},
}
tlsClientConfig := &tls.Config{
InsecureSkipVerify: true, // 忽略证书验证
}
cfg := elasticsearch.Config{
Addresses: conf.EsAddresses,
Username: conf.EsUserName,
Password: conf.EsPassword,
CACert: cert,
Transport: &http.Transport{
MaxIdleConnsPerHost: conf.EsMaxIdleConns, // 设置每个主机的最大空闲连接数
TLSClientConfig: tlsClientConfig,
},
}
client, err := elasticsearch.NewClient(cfg)
index := []string{"your-index-name"}
queryRes, err := EsSimpleSearch(client, query, index, true)


6. 一般我们都只关注 EsSearchHits 结构中的 Hits, 其解析示例代码如下

for _, hit := range queryRes.Hits.Hits {
yourObject := YourObject{}
if err := json.Unmarshal(hit.Source, & yourObject); err != nil {
continue
}
....
}

点赞(0) 打赏

微信小程序

微信扫一扫体验

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部