mongo.go 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. package initialize
  2. import (
  3. "context"
  4. "fmt"
  5. "github.com/flipped-aurora/gin-vue-admin/server/global"
  6. "github.com/flipped-aurora/gin-vue-admin/server/initialize/internal"
  7. "github.com/flipped-aurora/gin-vue-admin/server/utils"
  8. "github.com/pkg/errors"
  9. "github.com/qiniu/qmgo"
  10. "github.com/qiniu/qmgo/options"
  11. "go.mongodb.org/mongo-driver/bson"
  12. option "go.mongodb.org/mongo-driver/mongo/options"
  13. "sort"
  14. "strings"
  15. )
  16. var Mongo = new(mongo)
  17. type (
  18. mongo struct{}
  19. Index struct {
  20. V any `bson:"v"`
  21. Ns any `bson:"ns"`
  22. Key []bson.E `bson:"key"`
  23. Name string `bson:"name"`
  24. }
  25. )
  26. func (m *mongo) Indexes(ctx context.Context) error {
  27. // 表名:索引列表 列: "表名": [][]string{{"index1", "index2"}}
  28. indexMap := map[string][][]string{}
  29. for collection, indexes := range indexMap {
  30. err := m.CreateIndexes(ctx, collection, indexes)
  31. if err != nil {
  32. return err
  33. }
  34. }
  35. return nil
  36. }
  37. func (m *mongo) Initialization() error {
  38. var opts []options.ClientOptions
  39. if global.GVA_CONFIG.Mongo.IsZap {
  40. opts = internal.Mongo.GetClientOptions()
  41. }
  42. ctx := context.Background()
  43. config := &qmgo.Config{
  44. Uri: global.GVA_CONFIG.Mongo.Uri(),
  45. Coll: global.GVA_CONFIG.Mongo.Coll,
  46. Database: global.GVA_CONFIG.Mongo.Database,
  47. MinPoolSize: &global.GVA_CONFIG.Mongo.MinPoolSize,
  48. MaxPoolSize: &global.GVA_CONFIG.Mongo.MaxPoolSize,
  49. SocketTimeoutMS: &global.GVA_CONFIG.Mongo.SocketTimeoutMs,
  50. ConnectTimeoutMS: &global.GVA_CONFIG.Mongo.ConnectTimeoutMs,
  51. }
  52. if global.GVA_CONFIG.Mongo.Username != "" && global.GVA_CONFIG.Mongo.Password != "" {
  53. config.Auth = &qmgo.Credential{
  54. Username: global.GVA_CONFIG.Mongo.Username,
  55. Password: global.GVA_CONFIG.Mongo.Password,
  56. AuthSource: global.GVA_CONFIG.Mongo.AuthSource,
  57. }
  58. }
  59. client, err := qmgo.Open(ctx, config, opts...)
  60. if err != nil {
  61. return errors.Wrap(err, "链接mongodb数据库失败!")
  62. }
  63. global.GVA_MONGO = client
  64. err = m.Indexes(ctx)
  65. if err != nil {
  66. return err
  67. }
  68. return nil
  69. }
  70. func (m *mongo) CreateIndexes(ctx context.Context, name string, indexes [][]string) error {
  71. collection, err := global.GVA_MONGO.Database.Collection(name).CloneCollection()
  72. if err != nil {
  73. return errors.Wrapf(err, "获取[%s]的表对象失败!", name)
  74. }
  75. list, err := collection.Indexes().List(ctx)
  76. if err != nil {
  77. return errors.Wrapf(err, "获取[%s]的索引对象失败!", name)
  78. }
  79. var entities []Index
  80. err = list.All(ctx, &entities)
  81. if err != nil {
  82. return errors.Wrapf(err, "获取[%s]的索引列表失败!", name)
  83. }
  84. length := len(indexes)
  85. indexMap1 := make(map[string][]string, length)
  86. for i := 0; i < length; i++ {
  87. sort.Strings(indexes[i]) // 对索引key进行排序, 在使用bson.M搜索时, bson会自动按照key的字母顺序进行排序
  88. length1 := len(indexes[i])
  89. keys := make([]string, 0, length1)
  90. for j := 0; j < length1; j++ {
  91. if indexes[i][i][0] == '-' {
  92. keys = append(keys, indexes[i][j], "-1")
  93. continue
  94. }
  95. keys = append(keys, indexes[i][j], "1")
  96. }
  97. key := strings.Join(keys, "_")
  98. _, o1 := indexMap1[key]
  99. if o1 {
  100. return errors.Errorf("索引[%s]重复!", key)
  101. }
  102. indexMap1[key] = indexes[i]
  103. }
  104. length = len(entities)
  105. indexMap2 := make(map[string]map[string]string, length)
  106. for i := 0; i < length; i++ {
  107. v1, o1 := indexMap2[entities[i].Name]
  108. if !o1 {
  109. keyLength := len(entities[i].Key)
  110. v1 = make(map[string]string, keyLength)
  111. for j := 0; j < keyLength; j++ {
  112. v2, o2 := v1[entities[i].Key[j].Key]
  113. if !o2 {
  114. v1 = make(map[string]string)
  115. }
  116. v2 = entities[i].Key[j].Key
  117. v1[entities[i].Key[j].Key] = v2
  118. indexMap2[entities[i].Name] = v1
  119. }
  120. }
  121. }
  122. for k1, v1 := range indexMap1 {
  123. _, o2 := indexMap2[k1]
  124. if o2 {
  125. continue
  126. } // 索引存在
  127. if len(fmt.Sprintf("%s.%s.$%s", collection.Name(), name, v1)) > 127 {
  128. err = global.GVA_MONGO.Database.Collection(name).CreateOneIndex(ctx, options.IndexModel{
  129. Key: v1,
  130. IndexOptions: option.Index().SetName(utils.MD5V([]byte(k1))),
  131. // IndexOptions: option.Index().SetName(utils.MD5V([]byte(k1))).SetExpireAfterSeconds(86400), // SetExpireAfterSeconds(86400) 设置索引过期时间, 86400 = 1天
  132. })
  133. if err != nil {
  134. return errors.Wrapf(err, "创建索引[%s]失败!", k1)
  135. }
  136. return nil
  137. }
  138. err = global.GVA_MONGO.Database.Collection(name).CreateOneIndex(ctx, options.IndexModel{
  139. Key: v1,
  140. IndexOptions: option.Index().SetExpireAfterSeconds(86400),
  141. // IndexOptions: option.Index().SetName(utils.MD5V([]byte(k1))).SetExpireAfterSeconds(86400), // SetExpireAfterSeconds(86400) 设置索引过期时间(秒), 86400 = 1天
  142. })
  143. if err != nil {
  144. return errors.Wrapf(err, "创建索引[%s]失败!", k1)
  145. }
  146. }
  147. return nil
  148. }