Merge branch 'main' into for-dev

This commit is contained in:
ForDecember 2024-11-13 00:21:35 +08:00 committed by GitHub
commit 76285dc0e4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
22 changed files with 470 additions and 38 deletions

View File

@ -6,4 +6,8 @@ const (
func EnocunterMsgInit(m msg) {
m[ErrEaLinkInstert] = "路遇添加成功,但关联毛茸茸失败"
}
}
func EncounterMsgUserInit(m msg) {
m[ErrEaLinkInstert] = "路遇上传成功啦。但是不小心让毛茸茸跑丢了 /(ㄒoㄒ)/~~"
}

View File

@ -17,6 +17,7 @@ func init() {
// INGO
ErrMsgForUser = make(msg)
AnimalMsgUserInit(ErrMsgForUser)
EncounterMsgUserInit(ErrMsgForUser)
}
func GeneralMsgInit(m msg) {

View File

@ -71,4 +71,7 @@ const (
// GLM 部分
ErrorsGlmClientInitFail string = "GLM Client 初始化失败"
// ES 部分
ErrorsInitConnFail string = "初始化 Elasticsearch 连接失败"
)

View File

@ -9,10 +9,10 @@ import (
"strings"
"github.com/casbin/casbin/v2"
"github.com/elastic/go-elasticsearch/v8"
"github.com/yankeguo/zhipu"
"go.uber.org/zap"
"gorm.io/gorm"
)
var (
@ -46,6 +46,9 @@ var (
// GLM 全局客户端
GlmClient *zhipu.Client
// ES 全局客户端
ElasticClient *elasticsearch.Client
)
func init() {
@ -61,3 +64,20 @@ func init() {
log.Fatal(my_errors.ErrorsBasePath)
}
}
func init() {
// 1. 初始化程序根目录
if curPath, err := os.Getwd(); err == nil {
// 路径进行处理,兼容单元测试程序启动时的奇怪路径
if len(os.Args) > 1 && strings.HasPrefix(os.Args[1], "-test") {
// 替换 \ 为 /,然后移除 /test 及其后的内容
curPath = strings.ReplaceAll(curPath, "\\", "/")
parts := strings.Split(curPath, "/test")
BasePath = parts[0]
} else {
BasePath = curPath
}
} else {
log.Fatal(my_errors.ErrorsBasePath)
}
}

View File

@ -154,8 +154,8 @@ func (a *Animals) Create(context *gin.Context) {
avatar := photos[0]
avatarWidth := variable.ConfigYml.GetFloat64("FileUploadSetting.AvatarWidth")
srcPath := filepath.Join(variable.BasePath, variable.ConfigYml.GetString("FileUploadSetting.UploadFileSavePath"), "catsPhotos", "hum_"+userId, avatar)
dstPath := filepath.Join(variable.BasePath, variable.ConfigYml.GetString("FileUploadSetting.UploadFileSavePath"), "catsAvatar", avatar)
srcPath := filepath.Join(variable.ConfigYml.GetString("FileUploadSetting.UploadFileSavePath"), "catsPhotos", "hum_"+userId, avatar)
dstPath := filepath.Join(variable.ConfigYml.GetString("FileUploadSetting.UploadFileSavePath"), "catsAvatar", avatar)
avatarHeight, err := upload_file.ResizeImage(srcPath, dstPath, int(avatarWidth))
if err != nil {
response.Fail(context, consts.FilesUploadFailCode, consts.FilesUploadFailMsg, "")
@ -215,8 +215,8 @@ func (a *Animals) Create(context *gin.Context) {
// STAGE-3
if anm_id, ok := model.CreateAnimalFactory("").InsertDate(context); ok {
// 转移 photos 到 anm采用 rename dir 的方式
oldName := filepath.Join(variable.BasePath, variable.ConfigYml.GetString("FileUploadSetting.UploadFileSavePath"), "catsPhotos", "hum_"+userId)
newName := filepath.Join(variable.BasePath, variable.ConfigYml.GetString("FileUploadSetting.UploadFileSavePath"), "catsPhotos", "anm_"+strconv.FormatInt(anm_id, 10))
oldName := filepath.Join(variable.ConfigYml.GetString("FileUploadSetting.UploadFileSavePath"), "catsPhotos", "hum_"+userId)
newName := filepath.Join(variable.ConfigYml.GetString("FileUploadSetting.UploadFileSavePath"), "catsPhotos", "anm_"+strconv.FormatInt(anm_id, 10))
err := os.Rename(oldName, newName)
if err != nil {
// TODO 特殊返回,成功了一半?或者需要清空原有的操作?不过感觉这一步几乎不会出错。

View File

@ -6,6 +6,7 @@ import (
"catface/app/global/variable"
"catface/app/http/validator/core/data_transfer"
"catface/app/model"
"catface/app/model_es"
"catface/app/service/encounter/curd"
"catface/app/service/upload_file"
"catface/app/utils/response"
@ -25,8 +26,8 @@ func (e *Encounters) Create(context *gin.Context) {
avatar := photos[0]
avatarWidth := variable.ConfigYml.GetFloat64("FileUploadSetting.AvatarWidth")
srcPath := filepath.Join(variable.BasePath, variable.ConfigYml.GetString("FileUploadSetting.UploadFileSavePath"), "encounterPhotos", "hum_"+userId, avatar)
dstPath := filepath.Join(variable.BasePath, variable.ConfigYml.GetString("FileUploadSetting.UploadFileSavePath"), "encounterAvatar", avatar)
srcPath := filepath.Join(variable.ConfigYml.GetString("FileUploadSetting.UploadFileSavePath"), "encounterPhotos", "hum_"+userId, avatar)
dstPath := filepath.Join(variable.ConfigYml.GetString("FileUploadSetting.UploadFileSavePath"), "encounterAvatar", avatar)
avatarHeight, err := upload_file.ResizeImage(srcPath, dstPath, int(avatarWidth))
if err != nil {
response.Fail(context, consts.FilesUploadFailCode, consts.FilesUploadFailMsg, "")
@ -67,14 +68,21 @@ func (e *Encounters) Create(context *gin.Context) {
// STAGE -3: Real Insert - 1: ENC
animals_id := data_transfer.GetFloat64Slice(context, "animals_id") // 由于是 Slice 就交给 EAlink 内部遍历时处理。
// Real Insert - 2: EA LINK
if encounter_id, ok := model.CreateEncounterFactory("").InsertDate(context); ok && encounter_id > 0 {
if !model.CreateEncounterAnimalLinkFactory("").Insert(int64(encounter_id), animals_id) {
response.Fail(context, errcode.ErrEaLinkInstert, errcode.ErrMsg[errcode.ErrEaLinkInstert], "")
return
if encounter, ok := model.CreateEncounterFactory("").InsertDate(context); ok {
// 2: EA Links; // TIP 感觉直接使用 go 会直接且清晰。
go model.CreateEncounterAnimalLinkFactory("").Insert(encounter.Id, animals_id)
// if !model.CreateEncounterAnimalLinkFactory("").Insert(int64(encounter_id), animals_id) {
// response.Fail(context, errcode.ErrEaLinkInstert, errcode.ErrMsg[errcode.ErrEaLinkInstert], errcode.ErrMsgForUser[errcode.ErrEaLinkInstert])
// return
// }
// 3. ES speed
if level := int(context.GetFloat64(consts.ValidatorPrefix + "level")); level > 1 {
go model_es.CreateEncounterESFactory(&encounter).InsertDocument()
}
response.Success(context, consts.CurdStatusOkMsg, gin.H{
"encounter_id": encounter_id,
"encounter_id": encounter.Id,
})
} else {
response.Fail(context, consts.CurdCreatFailCode, consts.CurdCreatFailMsg+", 新增错误", "")

View File

@ -0,0 +1,40 @@
package web
import (
"catface/app/global/consts"
"catface/app/model"
"catface/app/model_es"
"catface/app/utils/response"
"github.com/gin-gonic/gin"
)
type Search struct {
}
/**
* @description: 全局搜索AnmName + Encounter
* @param {*gin.Context} context
* @return {*}
*/
func (s *Search) SearchAll(context *gin.Context) {
query := context.GetString(consts.ValidatorPrefix + "query")
var animals []model.Animal
var encounters []model.Encounter
// 1. Animal Name // TODO 增加字段的过滤,看前端了。
animals = model.CreateAnimalFactory("").ShowByName(query)
// 2. Encounter
encounterIds, _ := model_es.CreateEncounterESFactory(nil).QueryDocumentsMatchAll(query)
if len(encounterIds) > 0 {
encounters = model.CreateEncounterFactory("").ShowByIDs(encounterIds)
}
response.Success(context, consts.CurdStatusOkMsg, gin.H{
"animals": animals,
"encounters": encounters,
})
}

View File

@ -19,7 +19,7 @@ type Upload struct {
func (u *Upload) StartUpload(context *gin.Context) {
// TODO 如果之后要存储到 Linux 服务器上特殊路径下,就需要修改这里。
dir_name := context.GetString(consts.ValidatorPrefix + "dir_name")
savePath := filepath.Join(variable.BasePath, variable.ConfigYml.GetString("FileUploadSetting.UploadFileSavePath"), dir_name)
savePath := filepath.Join(variable.ConfigYml.GetString("FileUploadSetting.UploadFileSavePath"), dir_name)
if r, finnalSavePath := upload_file.Upload(context, savePath); r == true {
response.Success(context, consts.CurdStatusOkMsg, finnalSavePath)

View File

@ -10,6 +10,7 @@ import (
"catface/app/http/validator/web/encounter"
"catface/app/http/validator/web/encounter_like"
"catface/app/http/validator/web/nlp"
"catface/app/http/validator/web/search"
"catface/app/http/validator/web/users"
)
@ -81,4 +82,8 @@ func WebRegisterValidator() {
// TAG NLP
key = consts.ValidatorPrefix + "NlpTitle"
containers.Set(key, nlp.Title{})
// TAG Search
key = consts.ValidatorPrefix + "SearchAll"
containers.Set(key, search.SearchAll{})
}

View File

@ -19,6 +19,7 @@ type Create struct {
AnimalsId []int `form:"animals_id" json:"animals_id" binding:"required"`
Title string `form:"title" json:"title" binding:"required"`
Content string `form:"content" json:"content"`
Level int `form:"level" json:"level"`
// Avatar string `form:"avatar" json:"avatar"`
Photos []string `form:"photos" json:"photos"` // INFO 如果 Photo 为空,那就选取 Animals 的 Avatar

View File

@ -0,0 +1,30 @@
package search
import (
"catface/app/global/consts"
"catface/app/http/controller/web"
"catface/app/http/validator/core/data_transfer"
"catface/app/utils/response"
"github.com/gin-gonic/gin"
)
type SearchAll struct {
Query string `form:"query" json:"query"`
}
func (s SearchAll) CheckParams(context *gin.Context) {
if err := context.ShouldBind(&s); err != nil {
response.ValidatorError(context, err)
return
}
extraAddBindDataContext := data_transfer.DataAddContext(s, consts.ValidatorPrefix, context)
if extraAddBindDataContext == nil {
response.ErrorSystem(context, "Animal Create 表单验证器json化失败", "")
} else {
// 验证完成,调用控制器,并将验证器成员(字段)递给控制器,保持上下文数据一致性
(&web.Search{}).SearchAll(extraAddBindDataContext)
}
}

View File

@ -44,18 +44,22 @@ func (e *Encounter) TableName() string {
return "encounters"
}
func (e *Encounter) InsertDate(c *gin.Context) (int64, bool) {
var tmp Encounter
/**
* @description:
* @param {*gin.Context} c
* @return {*} 返回创建的绑定对象之后 model_es 的利用
*/
func (e *Encounter) InsertDate(c *gin.Context) (tmp Encounter, ok bool) {
if err := data_bind.ShouldBindFormDataToModel(c, &tmp); err == nil {
if res := e.Create(&tmp); res.Error == nil {
return tmp.Id, true
return tmp, true
} else {
variable.ZapLog.Error("Encounter 数据新增出错", zap.Error(res.Error))
}
} else {
variable.ZapLog.Error("Encounter 数据绑定出错", zap.Error(err))
}
return 0, false
return tmp, false
}
func formatEncounterList(rows *gorm.DB) (temp []EncounterList, err error) {
@ -169,6 +173,20 @@ func (e *Encounter) ShowByID(id int64) (temp *Encounter, err error) {
// return
}
func (e *Encounter) ShowByIDs(ids []int64, attrs ...string) (temp []Encounter) {
db := e.DB.Table(e.TableName())
if len(attrs) > 0 {
db = db.Select(attrs)
}
err := db.Where("id in (?)", ids).Find(&temp).Error
if err != nil {
variable.ZapLog.Error("Encounter ShowByIDs Error", zap.Error(err))
}
return
}
/**
* @description: 过去 1 个月发送过路遇表的 ids同时去重
* @param {*} user_id

View File

@ -141,17 +141,17 @@ func testInsertDeworming() {
}
func insertData() {
// testInsertSterilzation()
// fmt.Println("testInsertSterilzation success.")
testInsertSterilzation()
fmt.Println("testInsertSterilzation success.")
// testInsertBreed()
// fmt.Println("testInsertBreed success.")
testInsertBreed()
fmt.Println("testInsertBreed success.")
// testInsertStatus()
// fmt.Println("testInsertStatus success.")
testInsertStatus()
fmt.Println("testInsertStatus success.")
// testInsertAnmGender()
// fmt.Println("testInsertAnmGender success.")
testInsertAnmGender()
fmt.Println("testInsertAnmGender success.")
testInsertVaccination()
fmt.Println("testInsertVaccination success.")
@ -163,7 +163,8 @@ func insertData() {
func main() {
// 1.
dsn := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8mb4&parseTime=True&loc=Local",
"root", "Havocantelope412#", "113.44.68.213", "3306", "hav_cats") // ATT MySQL
// "root", "Havocantelope412#", "113.44.68.213", "3306", "hav_cats") // ATT MySQL dsn := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8mb4&parseTime=True&loc=Local",
"root", "havocantelope412", "127.0.0.1", "3306", "hav_cats") // ATT MySQL
fmt.Println("dsn:", dsn)
dbMySQL, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {

225
app/model_es/encounter.go Normal file
View File

@ -0,0 +1,225 @@
package model_es
import (
"bytes"
"catface/app/global/variable"
"catface/app/model"
"context"
"encoding/json"
"fmt"
"strings"
"github.com/elastic/go-elasticsearch/v8"
"github.com/elastic/go-elasticsearch/v8/esapi"
)
func CreateEncounterESFactory(encounter *model.Encounter) *Encounter {
if encounter == nil { // UPDATE 这样写好丑。
return &Encounter{}
}
// 我把数值绑定到了工厂创建当中。
return &Encounter{
Id: encounter.Id,
Title: encounter.Title,
Content: encounter.Content,
Tags: encounter.TagsSlice, // TODO 暂时没有对此字段的查询。
}
}
// INFO 存储能够作为索引存在的数据。
type Encounter struct {
Id int64 `json:"id"`
Title string `json:"title"`
Content string `json:"content"`
Tags []string `json:"tags"`
}
func (e *Encounter) IndexName() string {
return "catface_encounters"
}
func (e *Encounter) InsertDocument() error {
ctx := context.Background()
// 将结构体转换为 JSON 字符串
data, err := json.Marshal(e)
if err != nil {
return err
}
// 创建请求
req := esapi.IndexRequest{
Index: e.IndexName(),
DocumentID: fmt.Sprintf("%d", e.Id),
Body: bytes.NewReader(data),
Refresh: "true",
}
// 发送请求
res, err := req.Do(ctx, variable.ElasticClient)
if err != nil {
return err
}
defer res.Body.Close()
if res.IsError() {
var e map[string]interface{}
if err := json.NewDecoder(res.Body).Decode(&e); err != nil {
return fmt.Errorf("error parsing the response body: %s", err)
} else {
return fmt.Errorf("[%s] %s: %s",
res.Status(),
e["error"].(map[string]interface{})["type"],
e["error"].(map[string]interface{})["reason"],
)
}
}
return nil
}
// TODO 改正,仿 Insert
func (e *Encounter) UpdateDocument(client *elasticsearch.Client, encounter *Encounter) error {
ctx := context.Background()
// 将结构体转换为 JSON 字符串
data, err := json.Marshal(map[string]interface{}{
"doc": encounter,
})
if err != nil {
return err
}
// 创建请求
req := esapi.UpdateRequest{
Index: encounter.IndexName(),
DocumentID: fmt.Sprintf("%d", encounter.Id),
Body: bytes.NewReader(data),
Refresh: "true",
}
// 发送请求
res, err := req.Do(ctx, client)
if err != nil {
return err
}
defer res.Body.Close()
if res.IsError() {
var e map[string]interface{}
if err := json.NewDecoder(res.Body).Decode(&e); err != nil {
return fmt.Errorf("error parsing the response body: %s", err)
} else {
return fmt.Errorf("[%s] %s: %s",
res.Status(),
e["error"].(map[string]interface{})["type"],
e["error"].(map[string]interface{})["reason"],
)
}
}
return nil
}
/**
* @description: 粗略地包含各种关键词匹配
* @param {*elasticsearch.Client} client
* @param {string} query
* @return {*} 对应 Encounter id然后交给 MySQL 来查询详细的信息
*/
func (e *Encounter) QueryDocumentsMatchAll(query string) ([]int64, error) {
ctx := context.Background()
// 创建查询请求
req := esapi.SearchRequest{ // UPDATE 同时实现查询高亮?
Index: []string{e.IndexName()},
Body: strings.NewReader(fmt.Sprintf(`{
"_source": ["id"],
"query": {
"bool": {
"should": [
{
"match": {
"title": "%s"
}
},
{
"match": {
"content": "%s"
}
}
]
}
}
}`, query, query)),
}
// 发送请求
res, err := req.Do(ctx, variable.ElasticClient)
if err != nil {
return nil, err
}
defer res.Body.Close()
if res.IsError() {
var e map[string]interface{}
if err := json.NewDecoder(res.Body).Decode(&e); err != nil {
return nil, fmt.Errorf("error parsing the response body: %s", err)
} else {
return nil, fmt.Errorf("[%s] %s: %s",
res.Status(),
e["error"].(map[string]interface{})["type"],
e["error"].(map[string]interface{})["reason"],
)
}
}
// 解析响应
var r map[string]interface{}
if err := json.NewDecoder(res.Body).Decode(&r); err != nil {
return nil, err
}
// 提取命中结果
hits, ok := r["hits"].(map[string]interface{})["hits"].([]interface{})
if !ok {
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
// // 转换为 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
}

View File

@ -44,8 +44,9 @@ func Upload(context *gin.Context, savePath string) (r bool, finnalSavePath inter
}
// 文件上传可以设置按照 xxx年-xx月 格式存储
// INFO 但这个 returnPath 我还基本没有用到。
func generateYearMonthPath(savePathPre string) (string, string) {
returnPath := variable.BasePath + variable.ConfigYml.GetString("FileUploadSetting.UploadFileReturnPath")
returnPath := variable.BasePath + variable.ConfigYml.GetString("FileUploadSetting.UploadFileReturnPath") // UPDATE 因为没用到,所以就先不调整了。
curYearMonth := time.Now().In(time.Local).Format("2006_01")
newSavePathPre := filepath.Join(savePathPre, curYearMonth)
newReturnPathPre := filepath.Join(returnPath, curYearMonth)

View File

@ -16,6 +16,7 @@ import (
"log"
"os"
"github.com/elastic/go-elasticsearch/v8"
"github.com/yankeguo/zhipu"
)
@ -120,4 +121,13 @@ func init() {
log.Fatal(my_errors.ErrorsGlmClientInitFail + err.Error())
}
// 12. ES 客户端启动
variable.ElasticClient, err = elasticsearch.NewClient(elasticsearch.Config{
Addresses: []string{variable.ConfigYml.GetString("ElasticSearch.Addr")},
})
if err != nil {
log.Fatal(my_errors.ErrorsInitConnFail + err.Error())
}
}

View File

@ -35,7 +35,7 @@ Redis:
Logs:
GinLogName: "/store/logs/gin.log" #设置 gin 框架的接口访问日志
GoSkeletonLogName: "/store/logs/skeleton.log" #设置GoSkeleton项目骨架运行时日志文件名注意该名称不要与上一条重复 ,避免和 gin 框架的日志掺杂一起,造成混乱。
GoSkeletonLogName: "/store/logs/skeleton.log" #设置GoSkeleton项目骨架运行时日志文件名注意该名称不要与上一条重复 ,避免和 gin 框架的日志掺杂一起,造成混乱。
TextFormat: "json" #记录日志的格式参数选项console、json console 表示一般的文本格式
TimePrecision: "millisecond" #记录日志时相关的时间精度该参数选项second 、 millisecond 分别表示 秒 和 毫秒 ,默认为毫秒级别
MaxSize: 10 #每个日志的最大尺寸(以MB为单位 超过该值,系统将会自动进行切割
@ -56,11 +56,12 @@ SnowFlake:
SnowFlakeMachineId: 2 #如果本项目同时部署在多台机器并且需要同时使用该算法请为每一台机器设置不同的ID区间范围: [0,1023]
FileUploadSetting:
Size: 32 #设置上传文件的最大值单位M注意 如果go前置nginx服务器nginx 默认限制文件上传大小为 50 M ,用户上传文件限制还需要继续修改 nginx 配置
UploadFileField: "file" #post上传文件时表单的键名
UploadFileSavePath: "/public/nginx/" #上传文件保存在路径, 该路径与 BasePath 进行拼接使用
UploadFileReturnPath: "" # 文件上后返回的路径由于程序会自动创建软连接自动将资源定位到实际路径所有资源的访问入口建议都从public开始
AllowMimeType: #允许的文件mime类型列表
Size: 32 # 设置上传文件的最大值单位M注意 如果go前置nginx服务器nginx 默认限制文件上传大小为 50 M ,用户上传文件限制还需要继续修改 nginx 配置
UploadFileField: "file" # post上传文件时表单的键名
# TODO 为了方便后续兼容服务器上的 Nginx直接采取绝对路径
UploadFileSavePath: "D:/.File Data/GoProject/catface_back/public/nginx" # 上传文件保存在路径, 该路径与 BasePath 进行拼接使用
UploadFileReturnPath: "" # 文件上后返回的路径由于程序会自动创建软连接自动将资源定位到实际路径所有资源的访问入口建议都从public开始
AllowMimeType: #允许的文件mime类型列表
- "image/jpeg" #jpg、jpeg图片格式
- "image/png" #png图片格式
# - "image/x-icon" #ico图片
@ -155,7 +156,14 @@ Glm:
ApiKey: "0cf510ebc01599dba2a593069c1bdfbc.nQBQ4skP8xBh7ijU"
DefaultModel: "glm-4-flash"
# qiNiu 云存储配置
QiNiu:
AccessKey: "bI1MpHUBA9OCg4uSJkuJRmScuCJfOlbePe8fCENo"
SecretKey: "UP5-GmSmAYNbMlSb6LYLuKZ-fT35nlEzGvOKKm9S"
SecretKey: "UP5-GmSmAYNbMlSb6LYLuKZ-fT35nlEzGvOKKm9S"
ElasticSearch:
Addr: "http://localhost:9200"
UserName: "elastic"
Password: ""

View File

@ -5,7 +5,8 @@ Gormv2: # 只针对 gorm 操作数据库有效
IsInitGlobalGormMysql: 1 # 随项目启动为gorm db初始化一个全局 variable.GormDbMysql完全等于*gorm.Db,正确配置数据库,该值必须设置为: 1
SlowThreshold: 30 # 慢 SQL 阈值(sql执行时间超过此时间单位就会触发系统日志记录)
Write:
Host: "113.44.68.213"
# Host: "113.44.68.213"
Host: "127.0.0.1"
DataBase: "hav_cats"
Port: 3306
Prefix: "tb_" # 目前没有用到该配置项

View File

@ -149,6 +149,11 @@ func InitWebRouter() *gin.Engine {
{
nlp.POST("title", validatorFactory.Create(consts.ValidatorPrefix+"NlpTitle"))
}
search := backend.Group("search")
{
search.GET("", validatorFactory.Create(consts.ValidatorPrefix+"SearchAll"))
}
// }
}

50
test/es/encounter_test.go Normal file
View File

@ -0,0 +1,50 @@
package test
import (
"catface/app/global/variable"
"catface/app/model"
"catface/app/model_es"
_ "catface/bootstrap"
"fmt"
"testing"
)
func TestEncounterEs(t *testing.T) {
// 示例数据
encounterOri := &model.Encounter{
BaseModel: model.BaseModel{
Id: 4,
},
Title: "猪皮伤势轻,需静养猪皮伤势轻,需静养",
Content: "猪皮被带到医院检查了,拍片结果显示损伤不严重,静养即可自愈。建议这段时间不要折腾他,让老登好好休息。",
TagsSlice: []string{"猪皮", "脚伤", "骗保"},
}
encounter := model_es.CreateEncounterESFactory(encounterOri)
// 插入文档
// if err := encounter.InsertDocument(); err != nil {
// t.Fatalf("插入文档时出错: %s", err)
// }
go encounter.InsertDocument()
// // 更新文档
// encounter.Content = "更新: 猪皮被带到医院检查了,拍片结果显示损伤不严重,静养即可自愈。建议这段时间不要折腾他,让老登好好休息。"
// if err := encounter.UpdateDocument(variable.ElasticClient, encounter); err != nil {
// t.Fatalf("更新文档时出错: %s", err)
// }
// 查询文档
encounters, err := encounter.QueryDocumentsMatchAll(variable.ElasticClient, "猪皮")
if err != nil {
t.Fatalf("查询文档时出错: %s", err)
}
// for _, e := range encounters {
// fmt.Printf("ID: %d, 标题: %s, 内容: %s, 标签: %v\n", e.Id, e.Title, e.Content, e.Tags)
// }
for _, e := range encounters {
fmt.Printf("ID: %d\n", e)
}
}

View File

@ -13,7 +13,7 @@ func InitElastic() {
var err error
ElasticClient, err = elasticsearch.NewClient(elasticsearch.Config{
// Addresses: []string{"http://113.44.68.213:9200"},
Addresses: []string{"http://127.0.0.1:9200"},
Addresses: []string{"http://localhost:9200"}, // TIP 用 localhost 可以127.0.0.1 无效...
// Username: "elastic",
// Password: "U8n61yn*Sp4Kvbuqo_K8",
})

View File

@ -15,7 +15,8 @@ var DB *gorm.DB
func Init() {
dsn := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8mb4&parseTime=True&loc=Local",
"root", "Havocantelope412#", "113.44.68.213", "3306", "hav_cats") // danger MySQL
"root", "havocantelope412", "127.0.0.1", "3306", "hav_cats") // ATT MySQL
fmt.Println("dsn:", dsn)
dbMySQL, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {