finish add Knoledge

This commit is contained in:
Havoc412 2024-11-14 00:39:42 +08:00
parent 9ec55f46b4
commit 2502f43631
5 changed files with 201 additions and 43 deletions

View File

@ -27,14 +27,18 @@ func (s *Search) SearchAll(context *gin.Context) {
animals = model.CreateAnimalFactory("").ShowByName(query) animals = model.CreateAnimalFactory("").ShowByName(query)
// 2. Encounter // 2. Encounter
encounterIds, _ := model_es.CreateEncounterESFactory(nil).QueryDocumentsMatchAll(query) _, _ = model_es.CreateEncounterESFactory(nil).QueryDocumentsMatchAll(query)
if len(encounterIds) > 0 { // if len(encounterIds) > 0 {
encounters = model.CreateEncounterFactory("").ShowByIDs(encounterIds) // encounters = model.CreateEncounterFactory("").ShowByIDs(encounterIds)
} // }
// 3. Knowledge
knowledges, _ := model_es.CreateKnowledgeESFactory().QueryDocumentsMatchAll(query, 3)
response.Success(context, consts.CurdStatusOkMsg, gin.H{ response.Success(context, consts.CurdStatusOkMsg, gin.H{
"animals": animals, "animals": animals,
"encounters": encounters, "encounters": encounters,
"knowledges": knowledges,
}) })
} }

View File

@ -128,26 +128,22 @@ func (e *Encounter) UpdateDocument(client *elasticsearch.Client, encounter *Enco
* @param {string} query * @param {string} query
* @return {*} 对应 Encounter id然后交给 MySQL 来查询详细的信息 * @return {*} 对应 Encounter id然后交给 MySQL 来查询详细的信息
*/ */
func (e *Encounter) QueryDocumentsMatchAll(query string) ([]int64, error) { func (e *Encounter) QueryDocumentsMatchAll(query string) ([]Encounter, error) {
ctx := context.Background() ctx := context.Background()
// 创建查询请求 // 创建查询请求
req := esapi.SearchRequest{ // UPDATE 同时实现查询高亮? req := esapi.SearchRequest{ // UPDATE 同时实现查询高亮?
Index: []string{e.IndexName()}, Index: []string{e.IndexName()},
// INFO 采取高光的设定,所以还是用 ES 的返回值会比较好; "_source": ["id"],
Body: strings.NewReader(fmt.Sprintf(`{ Body: strings.NewReader(fmt.Sprintf(`{
"_source": ["id"],
"query": { "query": {
"bool": { "bool": {
"should": [ "should": [
{ {
"match": { "match": { "title": "%s" }
"title": "%s"
}
}, },
{ {
"match": { "match": { "content": "%s" }
"content": "%s"
}
} }
] ]
} }
@ -187,39 +183,37 @@ func (e *Encounter) QueryDocumentsMatchAll(query string) ([]int64, error) {
return nil, fmt.Errorf("error extracting hits from response") return nil, fmt.Errorf("error extracting hits from response")
} }
fmt.Println(hits) // // 转换为 id 切片
// var ids []int64
// 转换为 id 切片
var ids []int64
for _, hit := range hits {
hitMap := hit.(map[string]interface{})["_source"].(map[string]interface{})
id := int64(hitMap["id"].(float64))
ids = append(ids, id)
}
return ids, nil
// // 转换为 Encounter 切片
// var encounters []*Encounter
// for _, hit := range hits { // for _, hit := range hits {
// hitMap := hit.(map[string]interface{}) // hitMap := hit.(map[string]interface{})["_source"].(map[string]interface{})
// source := hitMap["_source"].(map[string]interface{}) // id := int64(hitMap["id"].(float64))
// ids = append(ids, id)
// // TIP 将 []interface{} 转换为 []string
// tagsInterface := source["tags"].([]interface{})
// tags := make([]string, len(tagsInterface))
// for i, tag := range tagsInterface {
// tags[i] = tag.(string)
// } // }
// return ids, nil
// encounter := &Encounter{ // 转换为 Encounter 切片
// Id: int64(source["id"].(float64)), var encounters []*Encounter
// Title: source["title"].(string), for _, hit := range hits {
// Content: source["content"].(string), hitMap := hit.(map[string]interface{})
// Tags: tags, source := hitMap["_source"].(map[string]interface{})
// } // highlight := hitMap["highlight"].(map[string]interface{})
// encounters = append(encounters, encounter)
// }
// return encounters, nil // TIP 将 []interface{} 转换为 []string
tagsInterface := source["tags"].([]interface{})
tags := make([]string, len(tagsInterface))
for i, tag := range tagsInterface {
tags[i] = tag.(string)
}
encounter := &Encounter{
Id: int64(source["id"].(float64)),
Title: source["title"].(string),
Content: source["content"].(string),
Tags: tags,
}
encounters = append(encounters, encounter)
}
return []Encounter{}, nil
} }

View File

@ -3,6 +3,8 @@ package model_es
import ( import (
"bytes" "bytes"
"catface/app/global/variable" "catface/app/global/variable"
"catface/app/utils/data_bind"
"catface/app/utils/model_handler"
"context" "context"
"encoding/json" "encoding/json"
"fmt" "fmt"
@ -142,3 +144,89 @@ func (k *Knowledge) RandomDocuments(num int) ([]*Knowledge, error) {
return documents, nil return documents, nil
} }
/**
* @description: 使用 ES match 匹配虽有字段同时处理 highlight
* @param {string} query 查询字符串
* @param {int} num 查询数量
* @return {*}
*/
func (k *Knowledge) QueryDocumentsMatchAll(query string, num int) ([]Knowledge, error) {
ctx := context.Background()
body := fmt.Sprintf(`{
"size": %d,
"query": {
"bool": {
"should": [
{ "match": {"title": "%s" }},
{ "match": {"content": "%s" }}
]
}
},
"highlight": {
"pre_tags": ["<em>"],
"post_tags": ["</em>"],
"fields": {
"title": {},
"content": {
"fragment_size" : 20
}
}
}
}`, num, query, query) // TODO dirs 我还没想好如何处理
// 创建请求
req := esapi.SearchRequest{
Index: []string{k.IndexName()},
Body: strings.NewReader(body),
}
// 发送请求
res, err := req.Do(ctx, variable.ElasticClient)
if err != nil {
return nil, err
}
defer res.Body.Close()
if res.IsError() {
var k map[string]interface{}
if err := json.NewDecoder(res.Body).Decode(&k); err != nil {
return nil, fmt.Errorf("error parsing the response body: %s", err)
} else {
return nil, fmt.Errorf("[%s] %s: %s",
res.Status(),
k["error"].(map[string]interface{})["type"],
k["error"].(map[string]interface{})["reason"],
)
}
}
var result map[string]interface{}
if err := json.NewDecoder(res.Body).Decode(&result); err != nil {
return nil, err
}
hits, ok := result["hits"].(map[string]interface{})["hits"].([]interface{})
if !ok {
return nil, fmt.Errorf("error extracting hits from response")
}
var knowledges []Knowledge
for _, hit := range hits {
hitMap := hit.(map[string]interface{})
source := hitMap["_source"].(map[string]interface{})
highlight := hitMap["highlight"].(map[string]interface{})
for k, v := range highlight {
source[k] = model_handler.TransStringSliceToString(v.([]interface{}))
}
var k Knowledge
if err := data_bind.ShouldBindFormMapToModel(source, &k); err != nil {
return nil, err
}
knowledges = append(knowledges, k)
}
return knowledges, nil
}

View File

@ -80,3 +80,64 @@ func fieldSetValue(c *gin.Context, valueOf reflect.Value, typeOf reflect.Type, c
} }
} }
} }
/**
* @description:
* @param {map[string]interface{}} m
* @param {interface{}} modelStruct
* @return {*}
*/
func ShouldBindFormMapToModel(m map[string]interface{}, modelStruct interface{}) error {
mTypeOf := reflect.TypeOf(modelStruct)
if mTypeOf.Kind() != reflect.Ptr {
return errors.New(modelStructMustPtr)
}
mValueOf := reflect.ValueOf(modelStruct)
mValueOfEle := mValueOf.Elem()
mtf := mValueOf.Elem().Type()
fieldNum := mtf.NumField()
for i := 0; i < fieldNum; i++ {
if !mtf.Field(i).Anonymous && mtf.Field(i).Type.Kind() != reflect.Struct {
fieldSetValueByMap(m, mValueOfEle, mtf, i)
} else if mtf.Field(i).Type.Kind() == reflect.Struct { // INFO 处理结构体。
// TODO 处理结构体(有名+匿名)
}
}
return nil
}
func fieldSetValueByMap(m map[string]interface{}, valueOf reflect.Value, typeOf reflect.Type, colIndex int) {
relaKey := typeOf.Field(colIndex).Tag.Get("json")
if relaKey != "-" {
switch typeOf.Field(colIndex).Type.Kind() {
case reflect.Int, reflect.Int16, reflect.Int32, reflect.Int64:
valueOf.Field(colIndex).SetInt(int64(m[relaKey].(float64)))
return
case reflect.Float32, reflect.Float64:
valueOf.Field(colIndex).SetFloat(m[relaKey].(float64))
return
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
valueOf.Field(colIndex).SetUint(uint64(m[relaKey].(float64)))
return
case reflect.String:
valueOf.Field(colIndex).SetString(m[relaKey].(string))
return
case reflect.Bool:
valueOf.Field(colIndex).SetBool(m[relaKey].(bool))
return
case reflect.Slice:
interfaceSlice := m[relaKey].([]interface{})
stringSlice := make([]string, len(interfaceSlice))
// 遍历并进行类型断言
for i, v := range interfaceSlice {
stringSlice[i] = v.(string)
}
// 设置字段值
valueOf.Field(colIndex).Set(reflect.ValueOf(stringSlice))
return
default:
return
}
}
}

View File

@ -0,0 +1,11 @@
package model_handler
func TransStringSliceToString(strs []interface{}) string {
var result string
for _, str := range strs {
if s, ok := str.(string); ok {
result += s
}
}
return result
}