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)
|
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,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
}
|
||||||
|
@ -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