Files
mayfly-go/server/internal/mongo/api/mongo.go
zongyangleo 142bbd265d !134 feat: 新增支持es和连接池
* feat: 各连接,支持连接池
* feat:支持es
2025-05-21 04:42:30 +00:00

290 lines
8.3 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package api
import (
"context"
"mayfly-go/internal/event"
"mayfly-go/internal/mongo/api/form"
"mayfly-go/internal/mongo/api/vo"
"mayfly-go/internal/mongo/application"
"mayfly-go/internal/mongo/domain/entity"
"mayfly-go/internal/mongo/imsg"
"mayfly-go/internal/mongo/mgm"
"mayfly-go/internal/pkg/consts"
tagapp "mayfly-go/internal/tag/application"
tagentity "mayfly-go/internal/tag/domain/entity"
"mayfly-go/pkg/biz"
"mayfly-go/pkg/global"
"mayfly-go/pkg/model"
"mayfly-go/pkg/req"
"mayfly-go/pkg/utils/collx"
"regexp"
"strings"
"github.com/may-fly/cast"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
"go.mongodb.org/mongo-driver/mongo/options"
)
type Mongo struct {
mongoApp application.Mongo `inject:"T"`
tagTreeApp tagapp.TagTree `inject:"T"`
}
func (ma *Mongo) ReqConfs() *req.Confs {
saveDataPerm := req.NewPermission("mongo:data:save")
reqs := [...]*req.Conf{
// 获取所有mongo列表
req.NewGet("", ma.Mongos),
req.NewPost("/test-conn", ma.TestConn),
req.NewPost("", ma.Save).Log(req.NewLogSaveI(imsg.LogMongoSave)),
req.NewDelete(":id", ma.DeleteMongo).Log(req.NewLogSaveI(imsg.LogMongoDelete)),
// 获取mongo下的所有数据库
req.NewGet(":id/databases", ma.Databases),
// 获取mongo指定库的所有集合
req.NewGet(":id/collections", ma.Collections),
// mongo runCommand
req.NewPost(":id/run-command", ma.RunCommand).Log(req.NewLogSaveI(imsg.LogMongoRunCmd)),
// 执行mongo find命令
req.NewPost(":id/command/find", ma.FindCommand),
req.NewPost(":id/command/update-by-id", ma.UpdateByIdCommand).RequiredPermission(saveDataPerm).Log(req.NewLogSaveI(imsg.LogUpdateDocs)),
// 执行mongo delete by id命令
req.NewPost(":id/command/delete-by-id", ma.DeleteByIdCommand).RequiredPermission(req.NewPermission("mongo:data:del")).Log(req.NewLogSaveI(imsg.LogDelDocs)),
// 执行mongo insert 命令
req.NewPost(":id/command/insert", ma.InsertOneCommand).RequiredPermission(saveDataPerm).Log(req.NewLogSaveI(imsg.LogInsertDocs)),
}
return req.NewConfs("/mongos", reqs[:]...)
}
func (m *Mongo) Mongos(rc *req.Ctx) {
queryCond := req.BindQuery(rc, new(entity.MongoQuery))
// 不存在可访问标签id即没有可操作数据
tags := m.tagTreeApp.GetAccountTags(rc.GetLoginAccount().Id, &tagentity.TagTreeQuery{
TypePaths: collx.AsArray(tagentity.NewTypePaths(tagentity.TagTypeMongo)),
CodePathLikes: []string{queryCond.TagPath},
})
if len(tags) == 0 {
rc.ResData = model.NewEmptyPageResult[any]()
return
}
queryCond.Codes = tags.GetCodes()
res, err := m.mongoApp.GetPageList(queryCond)
biz.ErrIsNil(err)
resVo := model.PageResultConv[*entity.Mongo, *vo.Mongo](res)
mongovos := resVo.List
// 填充标签信息
m.tagTreeApp.FillTagInfo(tagentity.TagType(consts.ResourceTypeMongo), collx.ArrayMap(mongovos, func(mvo *vo.Mongo) tagentity.ITagResource {
return mvo
})...)
rc.ResData = resVo
}
func (m *Mongo) TestConn(rc *req.Ctx) {
form := &form.Mongo{}
mongo := req.BindJsonAndCopyTo[*entity.Mongo](rc, form, new(entity.Mongo))
biz.ErrIsNilAppendErr(m.mongoApp.TestConn(mongo), "connection error: %s")
}
func (m *Mongo) Save(rc *req.Ctx) {
form := &form.Mongo{}
mongo := req.BindJsonAndCopyTo[*entity.Mongo](rc, form, new(entity.Mongo))
// 密码脱敏记录日志
form.Uri = func(str string) string {
reg := regexp.MustCompile(`(^mongodb://.+?:)(.+)(@.+$)`)
return reg.ReplaceAllString(str, `${1}****${3}`)
}(form.Uri)
rc.ReqParam = form
biz.ErrIsNil(m.mongoApp.SaveMongo(rc.MetaCtx, mongo, form.TagCodePaths...))
}
func (m *Mongo) DeleteMongo(rc *req.Ctx) {
idsStr := rc.PathParam("id")
rc.ReqParam = idsStr
ids := strings.Split(idsStr, ",")
for _, v := range ids {
m.mongoApp.Delete(rc.MetaCtx, cast.ToUint64(v))
}
}
func (m *Mongo) Databases(rc *req.Ctx) {
conn, err := m.mongoApp.GetMongoConn(m.GetMongoId(rc))
biz.ErrIsNil(err)
defer mgm.PutMongoConn(conn)
res, err := conn.Cli.ListDatabases(context.TODO(), bson.D{})
biz.ErrIsNilAppendErr(err, "get mongo dbs error: %s")
rc.ResData = res
}
func (m *Mongo) Collections(rc *req.Ctx) {
conn, err := m.mongoApp.GetMongoConn(m.GetMongoId(rc))
biz.ErrIsNil(err)
defer mgm.PutMongoConn(conn)
global.EventBus.Publish(rc.MetaCtx, event.EventTopicResourceOp, conn.Info.CodePath[0])
db := rc.Query("database")
biz.NotEmpty(db, "database cannot be empty")
ctx := context.TODO()
res, err := conn.Cli.Database(db).ListCollectionNames(ctx, bson.D{})
biz.ErrIsNilAppendErr(err, "get db collections error: %s")
rc.ResData = res
}
func (m *Mongo) RunCommand(rc *req.Ctx) {
commandForm := new(form.MongoRunCommand)
req.BindJsonAndValid(rc, commandForm)
conn, err := m.mongoApp.GetMongoConn(m.GetMongoId(rc))
biz.ErrIsNil(err)
defer mgm.PutMongoConn(conn)
rc.ReqParam = collx.Kvs("mongo", conn.Info, "cmd", commandForm)
// 顺序执行
commands := bson.D{}
for _, cmd := range commandForm.Command {
e := bson.E{}
for k, v := range cmd {
e.Key = k
e.Value = v
}
commands = append(commands, e)
}
ctx := context.TODO()
var bm bson.M
err = conn.Cli.Database(commandForm.Database).RunCommand(
ctx,
commands,
).Decode(&bm)
biz.ErrIsNilAppendErr(err, "command execution failed: %s")
rc.ResData = bm
}
func (m *Mongo) FindCommand(rc *req.Ctx) {
commandForm := req.BindJsonAndValid(rc, new(form.MongoFindCommand))
conn, err := m.mongoApp.GetMongoConn(m.GetMongoId(rc))
biz.ErrIsNil(err)
defer mgm.PutMongoConn(conn)
cli := conn.Cli
limit := commandForm.Limit
if limit != 0 {
biz.IsTrue(limit <= 100, "the limit cannot exceed 100")
}
opts := options.Find().SetSort(commandForm.Sort).
SetSkip(commandForm.Skip).
SetLimit(limit)
ctx := context.TODO()
filter := commandForm.Filter
// 处理_id查询字段,使用ObjectId函数包装
id, ok := filter["_id"].(string)
if ok && id != "" {
objId, err := primitive.ObjectIDFromHex(id)
if err == nil {
filter["_id"] = objId
}
}
cur, err := cli.Database(commandForm.Database).Collection(commandForm.Collection).Find(ctx, commandForm.Filter, opts)
biz.ErrIsNilAppendErr(err, "command execution failed: %s")
var res []bson.M
cur.All(ctx, &res)
rc.ResData = res
}
func (m *Mongo) UpdateByIdCommand(rc *req.Ctx) {
commandForm := req.BindJsonAndValid(rc, new(form.MongoUpdateByIdCommand))
conn, err := m.mongoApp.GetMongoConn(m.GetMongoId(rc))
biz.ErrIsNil(err)
defer mgm.PutMongoConn(conn)
rc.ReqParam = collx.Kvs("mongo", conn.Info, "cmd", commandForm)
// 解析docId文档id如果为string类型则使用ObjectId解析解析失败则为普通字符串
docId := commandForm.DocId
docIdVal, ok := docId.(string)
if ok {
objId, err := primitive.ObjectIDFromHex(docIdVal)
if err == nil {
docId = objId
}
}
res, err := conn.Cli.Database(commandForm.Database).Collection(commandForm.Collection).UpdateByID(context.TODO(), docId, commandForm.Update)
biz.ErrIsNilAppendErr(err, "command execution failed: %s")
rc.ResData = res
}
func (m *Mongo) DeleteByIdCommand(rc *req.Ctx) {
commandForm := req.BindJsonAndValid(rc, new(form.MongoUpdateByIdCommand))
conn, err := m.mongoApp.GetMongoConn(m.GetMongoId(rc))
biz.ErrIsNil(err)
defer mgm.PutMongoConn(conn)
rc.ReqParam = collx.Kvs("mongo", conn.Info, "cmd", commandForm)
// 解析docId文档id如果为string类型则使用ObjectId解析解析失败则为普通字符串
docId := commandForm.DocId
docIdVal, ok := docId.(string)
if ok {
objId, err := primitive.ObjectIDFromHex(docIdVal)
if err == nil {
docId = objId
}
}
res, err := conn.Cli.Database(commandForm.Database).Collection(commandForm.Collection).DeleteOne(context.TODO(), bson.D{{Key: "_id", Value: docId}})
biz.ErrIsNilAppendErr(err, "command execution failed: %s")
rc.ResData = res
}
func (m *Mongo) InsertOneCommand(rc *req.Ctx) {
commandForm := req.BindJsonAndValid(rc, new(form.MongoInsertCommand))
conn, err := m.mongoApp.GetMongoConn(m.GetMongoId(rc))
biz.ErrIsNil(err)
defer mgm.PutMongoConn(conn)
rc.ReqParam = collx.Kvs("mongo", conn.Info, "cmd", commandForm)
res, err := conn.Cli.Database(commandForm.Database).Collection(commandForm.Collection).InsertOne(context.TODO(), commandForm.Doc)
biz.ErrIsNilAppendErr(err, "command execution failed: %s")
rc.ResData = res
}
// 获取请求路径上的mongo id
func (m *Mongo) GetMongoId(rc *req.Ctx) uint64 {
dbId := rc.PathParamInt("id")
biz.IsTrue(dbId > 0, "mongoId error")
return uint64(dbId)
}