mongo.go 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. package initialize
  2. import (
  3. "context"
  4. "fmt"
  5. "github.com/pkg/errors"
  6. "github.com/qiniu/qmgo"
  7. "github.com/qiniu/qmgo/options"
  8. "go.mongodb.org/mongo-driver/bson"
  9. option "go.mongodb.org/mongo-driver/mongo/options"
  10. "server/global"
  11. "server/initialize/internal"
  12. "server/utils"
  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. client, err := qmgo.Open(ctx, &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. Auth: &qmgo.Credential{
  52. Username: global.GVA_CONFIG.Mongo.Username,
  53. Password: global.GVA_CONFIG.Mongo.Password,
  54. AuthSource: global.GVA_CONFIG.Mongo.AuthSource,
  55. },
  56. }, opts...)
  57. if err != nil {
  58. return errors.Wrap(err, "链接mongodb数据库失败!")
  59. }
  60. global.GVA_MONGO = client
  61. err = m.Indexes(ctx)
  62. if err != nil {
  63. return err
  64. }
  65. return nil
  66. }
  67. func (m *mongo) CreateIndexes(ctx context.Context, name string, indexes [][]string) error {
  68. collection, err := global.GVA_MONGO.Database.Collection(name).CloneCollection()
  69. if err != nil {
  70. return errors.Wrapf(err, "获取[%s]的表对象失败!", name)
  71. }
  72. list, err := collection.Indexes().List(ctx)
  73. if err != nil {
  74. return errors.Wrapf(err, "获取[%s]的索引对象失败!", name)
  75. }
  76. var entities []Index
  77. err = list.All(ctx, &entities)
  78. if err != nil {
  79. return errors.Wrapf(err, "获取[%s]的索引列表失败!", name)
  80. }
  81. length := len(indexes)
  82. indexMap1 := make(map[string][]string, length)
  83. for i := 0; i < length; i++ {
  84. sort.Strings(indexes[i]) // 对索引key进行排序, 在使用bson.M搜索时, bson会自动按照key的字母顺序进行排序
  85. length1 := len(indexes[i])
  86. keys := make([]string, 0, length1)
  87. for j := 0; j < length1; j++ {
  88. if indexes[i][i][0] == '-' {
  89. keys = append(keys, indexes[i][j], "-1")
  90. continue
  91. }
  92. keys = append(keys, indexes[i][j], "1")
  93. }
  94. key := strings.Join(keys, "_")
  95. _, o1 := indexMap1[key]
  96. if o1 {
  97. return errors.Errorf("索引[%s]重复!", key)
  98. }
  99. indexMap1[key] = indexes[i]
  100. }
  101. length = len(entities)
  102. indexMap2 := make(map[string]map[string]string, length)
  103. for i := 0; i < length; i++ {
  104. v1, o1 := indexMap2[entities[i].Name]
  105. if !o1 {
  106. keyLength := len(entities[i].Key)
  107. v1 = make(map[string]string, keyLength)
  108. for j := 0; j < keyLength; j++ {
  109. v2, o2 := v1[entities[i].Key[j].Key]
  110. if !o2 {
  111. v1 = make(map[string]string)
  112. }
  113. v2 = entities[i].Key[j].Key
  114. v1[entities[i].Key[j].Key] = v2
  115. indexMap2[entities[i].Name] = v1
  116. }
  117. }
  118. }
  119. for k1, v1 := range indexMap1 {
  120. _, o2 := indexMap2[k1]
  121. if o2 {
  122. continue
  123. } // 索引存在
  124. if len(fmt.Sprintf("%s.%s.$%s", collection.Name(), name, v1)) > 127 {
  125. err = global.GVA_MONGO.Database.Collection(name).CreateOneIndex(ctx, options.IndexModel{
  126. Key: v1,
  127. IndexOptions: option.Index().SetName(utils.MD5V([]byte(k1))),
  128. // IndexOptions: option.Index().SetName(utils.MD5V([]byte(k1))).SetExpireAfterSeconds(86400), // SetExpireAfterSeconds(86400) 设置索引过期时间, 86400 = 1天
  129. })
  130. if err != nil {
  131. return errors.Wrapf(err, "创建索引[%s]失败!", k1)
  132. }
  133. return nil
  134. }
  135. err = global.GVA_MONGO.Database.Collection(name).CreateOneIndex(ctx, options.IndexModel{
  136. Key: v1,
  137. IndexOptions: option.Index().SetExpireAfterSeconds(86400),
  138. // IndexOptions: option.Index().SetName(utils.MD5V([]byte(k1))).SetExpireAfterSeconds(86400), // SetExpireAfterSeconds(86400) 设置索引过期时间(秒), 86400 = 1天
  139. })
  140. if err != nil {
  141. return errors.Wrapf(err, "创建索引[%s]失败!", k1)
  142. }
  143. }
  144. return nil
  145. }