finish add Knoledge
This commit is contained in:
parent
9ec55f46b4
commit
2502f43631
@ -27,14 +27,18 @@ func (s *Search) SearchAll(context *gin.Context) {
|
||||
animals = model.CreateAnimalFactory("").ShowByName(query)
|
||||
|
||||
// 2. Encounter
|
||||
encounterIds, _ := model_es.CreateEncounterESFactory(nil).QueryDocumentsMatchAll(query)
|
||||
_, _ = model_es.CreateEncounterESFactory(nil).QueryDocumentsMatchAll(query)
|
||||
|
||||
if len(encounterIds) > 0 {
|
||||
encounters = model.CreateEncounterFactory("").ShowByIDs(encounterIds)
|
||||
}
|
||||
// if len(encounterIds) > 0 {
|
||||
// encounters = model.CreateEncounterFactory("").ShowByIDs(encounterIds)
|
||||
// }
|
||||
|
||||
// 3. Knowledge
|
||||
knowledges, _ := model_es.CreateKnowledgeESFactory().QueryDocumentsMatchAll(query, 3)
|
||||
|
||||
response.Success(context, consts.CurdStatusOkMsg, gin.H{
|
||||
"animals": animals,
|
||||
"encounters": encounters,
|
||||
"knowledges": knowledges,
|
||||
})
|
||||
}
|
||||
|
@ -128,26 +128,22 @@ func (e *Encounter) UpdateDocument(client *elasticsearch.Client, encounter *Enco
|
||||
* @param {string} query
|
||||
* @return {*} 对应 Encounter 的 id,然后交给 MySQL 来查询详细的信息?
|
||||
*/
|
||||
func (e *Encounter) QueryDocumentsMatchAll(query string) ([]int64, error) {
|
||||
func (e *Encounter) QueryDocumentsMatchAll(query string) ([]Encounter, error) {
|
||||
ctx := context.Background()
|
||||
|
||||
// 创建查询请求
|
||||
req := esapi.SearchRequest{ // UPDATE 同时实现查询高亮?
|
||||
Index: []string{e.IndexName()},
|
||||
// INFO 采取高光的设定,所以还是用 ES 的返回值会比较好; "_source": ["id"],
|
||||
Body: strings.NewReader(fmt.Sprintf(`{
|
||||
"_source": ["id"],
|
||||
"query": {
|
||||
"bool": {
|
||||
"should": [
|
||||
{
|
||||
"match": {
|
||||
"title": "%s"
|
||||
}
|
||||
"match": { "title": "%s" }
|
||||
},
|
||||
{
|
||||
"match": {
|
||||
"content": "%s"
|
||||
}
|
||||
"match": { "content": "%s" }
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -187,39 +183,37 @@ func (e *Encounter) QueryDocumentsMatchAll(query string) ([]int64, error) {
|
||||
return nil, fmt.Errorf("error extracting hits from response")
|
||||
}
|
||||
|
||||
fmt.Println(hits)
|
||||
// // 转换为 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
|
||||
|
||||
// 转换为 id 切片
|
||||
var ids []int64
|
||||
// 转换为 Encounter 切片
|
||||
var encounters []*Encounter
|
||||
for _, hit := range hits {
|
||||
hitMap := hit.(map[string]interface{})["_source"].(map[string]interface{})
|
||||
id := int64(hitMap["id"].(float64))
|
||||
ids = append(ids, id)
|
||||
hitMap := hit.(map[string]interface{})
|
||||
source := hitMap["_source"].(map[string]interface{})
|
||||
// highlight := hitMap["highlight"].(map[string]interface{})
|
||||
|
||||
// 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 ids, nil
|
||||
|
||||
// // 转换为 Encounter 切片
|
||||
// var encounters []*Encounter
|
||||
// for _, hit := range hits {
|
||||
// hitMap := hit.(map[string]interface{})
|
||||
// source := hitMap["_source"].(map[string]interface{})
|
||||
|
||||
// // 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 encounters, nil
|
||||
return []Encounter{}, nil
|
||||
}
|
||||
|
@ -3,6 +3,8 @@ package model_es
|
||||
import (
|
||||
"bytes"
|
||||
"catface/app/global/variable"
|
||||
"catface/app/utils/data_bind"
|
||||
"catface/app/utils/model_handler"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
@ -142,3 +144,89 @@ func (k *Knowledge) RandomDocuments(num int) ([]*Knowledge, error) {
|
||||
|
||||
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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
11
app/utils/model_handler/model_es_handler.go
Normal file
11
app/utils/model_handler/model_es_handler.go
Normal 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
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user