simCardManageRepo.go 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327
  1. package mongo
  2. import (
  3. "context"
  4. "fmt"
  5. "fwh-toolbox-server/database"
  6. "fwh-toolbox-server/domain"
  7. "fwh-toolbox-server/dto"
  8. "strings"
  9. "time"
  10. "go.mongodb.org/mongo-driver/bson"
  11. "go.mongodb.org/mongo-driver/mongo"
  12. "go.mongodb.org/mongo-driver/mongo/options"
  13. "go.uber.org/zap"
  14. )
  15. const (
  16. CollectionName_SimCardManage = "SimCardManage"
  17. CollectionName_SimCardMonthlyData = "SimCardMonthlyData"
  18. )
  19. // 查询SIM卡信息(批量)
  20. func GetSimCardBatchInfo(page, size uint, search string, status *string, platform *string) (*dto.ResPage[domain.SimCardInfo], error) {
  21. ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
  22. defer cancel()
  23. collection := database.GetCollection(CollectionName_SimCardManage)
  24. // 查询条件
  25. filter := bson.M{}
  26. // 搜索 _id (GICCID)
  27. if search != "" {
  28. filter["_id"] = bson.M{
  29. "$regex": search,
  30. "$options": "i", // 不区分大小写,可去掉
  31. }
  32. }
  33. // 过滤状态(支持逗号分隔多值)
  34. if status != nil {
  35. parts := strings.Split(*status, ",")
  36. if len(parts) == 1 {
  37. filter["status"] = bson.M{"$eq": parts[0]}
  38. } else {
  39. filter["status"] = bson.M{"$in": parts}
  40. }
  41. }
  42. // 过滤平台(支持逗号分隔多值)
  43. if platform != nil {
  44. parts := strings.Split(*platform, ",")
  45. if len(parts) == 1 {
  46. filter["platform"] = bson.M{"$eq": parts[0]}
  47. } else {
  48. filter["platform"] = bson.M{"$in": parts}
  49. }
  50. }
  51. findOptions := options.Find().
  52. SetSkip(int64((page - 1) * size)).
  53. SetLimit(int64(size)).
  54. SetSort(bson.D{
  55. {Key: "allDataUsage", Value: -1}, // 降序
  56. })
  57. cursor, err := collection.Find(ctx, filter, findOptions)
  58. if err != nil {
  59. return nil, err
  60. }
  61. defer cursor.Close(ctx)
  62. var infoList []domain.SimCardInfo
  63. for cursor.Next(ctx) {
  64. var info domain.SimCardInfo
  65. if err := cursor.Decode(&info); err != nil {
  66. return nil, err
  67. }
  68. infoList = append(infoList, info)
  69. }
  70. // 查询总数(须与查询条件一致,否则带 search/status/platform 筛选时 total 不准)
  71. total, err := collection.CountDocuments(ctx, filter)
  72. if err != nil {
  73. return nil, err
  74. }
  75. res := dto.ResPage[domain.SimCardInfo]{
  76. Data: infoList,
  77. PageSize: size,
  78. PageNum: page,
  79. Total: uint(total),
  80. }
  81. return &res, nil
  82. }
  83. // 查询SIM卡信息(单卡)
  84. func GetSimCardInfo(id string) (*domain.SimCardInfo, error) {
  85. ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
  86. defer cancel()
  87. collection := database.GetCollection(CollectionName_SimCardManage)
  88. var info domain.SimCardInfo
  89. err := collection.FindOne(ctx, bson.M{"_id": id}).Decode(&info)
  90. if err != nil {
  91. return nil, err
  92. }
  93. return &info, nil
  94. }
  95. // GetSimCardInfoByIDs 按 GICCID 列表批量查询 SIM 卡信息(_id $in)。
  96. // 返回命中的记录(未命中的 GICCID 不会出现在结果中),按 allDataUsage 降序。
  97. func GetSimCardInfoByIDs(ids []string) ([]domain.SimCardInfo, error) {
  98. ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
  99. defer cancel()
  100. collection := database.GetCollection(CollectionName_SimCardManage)
  101. filter := bson.M{"_id": bson.M{"$in": ids}}
  102. findOptions := options.Find().SetSort(bson.D{{Key: "allDataUsage", Value: -1}})
  103. cursor, err := collection.Find(ctx, filter, findOptions)
  104. if err != nil {
  105. return nil, err
  106. }
  107. defer cursor.Close(ctx)
  108. var infoList []domain.SimCardInfo
  109. if err := cursor.All(ctx, &infoList); err != nil {
  110. return nil, err
  111. }
  112. return infoList, nil
  113. }
  114. // 查询SIM卡月数据(单卡)
  115. func GetSimCardMonthlyData(month string, id string) (*domain.SimCardMonthlyData, error) {
  116. ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
  117. defer cancel()
  118. collection := database.GetCollection(CollectionName_SimCardMonthlyData)
  119. var info domain.SimCardMonthlyData
  120. err := collection.FindOne(ctx, bson.M{"simId": id, "month": month}).Decode(&info)
  121. if err != nil {
  122. return nil, err
  123. }
  124. return &info, nil
  125. }
  126. // 插入SIM卡基本信息数据
  127. func UpdateSimCardInfo(info domain.SimCardInfo) error {
  128. ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
  129. defer cancel()
  130. collection := database.GetCollection(CollectionName_SimCardManage)
  131. filter := bson.M{"_id": info.GICCID} // 按ID匹配
  132. _, err := collection.ReplaceOne(ctx, filter, info, options.Replace().SetUpsert(true))
  133. if err != nil {
  134. return err
  135. }
  136. return nil
  137. }
  138. // 批量插入SIM卡基本信息数据
  139. func UpdateSimCardBatchInfo(infoList []domain.SimCardInfo) (int64, error) {
  140. ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
  141. defer cancel()
  142. collection := database.GetCollection(CollectionName_SimCardManage)
  143. batchSize := 1000
  144. var totalInserted int64
  145. for start := 0; start < len(infoList); start += batchSize {
  146. end := start + batchSize
  147. if end > len(infoList) {
  148. end = len(infoList)
  149. }
  150. models := make([]mongo.WriteModel, 0, end-start)
  151. for _, doc := range infoList[start:end] {
  152. model := mongo.NewReplaceOneModel().
  153. SetFilter(bson.M{
  154. "_id": doc.GICCID,
  155. }).
  156. SetReplacement(doc).
  157. SetUpsert(true)
  158. models = append(models, model)
  159. }
  160. result, err := collection.BulkWrite(
  161. ctx,
  162. models,
  163. options.BulkWrite().
  164. SetOrdered(false),
  165. )
  166. if err != nil {
  167. zap.L().Error("UpdateSimCardBatchInfo bulk insert failed.", zap.String("err", err.Error()), zap.Int("start", start), zap.Int("end", end), zap.Int64("totalInserted", totalInserted))
  168. return totalInserted, fmt.Errorf(
  169. "bulk insert failed (%d~%d): %w",
  170. start,
  171. end,
  172. err,
  173. )
  174. }
  175. totalInserted += result.InsertedCount
  176. }
  177. return totalInserted, nil
  178. }
  179. // 插入SIM卡日流量数据
  180. func UpdateSimCardDayData(data domain.SimCardDayData) error {
  181. ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
  182. defer cancel()
  183. collection := database.GetCollection(CollectionName_SimCardMonthlyData)
  184. dailyUsageField := fmt.Sprintf(
  185. "dailyUsage.%d",
  186. data.Day,
  187. )
  188. update := bson.M{
  189. "$set": bson.M{
  190. "allDataUsage": data.AllDataUsage,
  191. "updateTime": data.UpdateTime,
  192. dailyUsageField: data.DailyUsage,
  193. },
  194. "$setOnInsert": bson.M{
  195. "simId": data.SimId,
  196. "month": data.Month,
  197. },
  198. }
  199. filter := bson.M{"simId": data.SimId, "month": data.Month} // 按ID和month匹配
  200. _, err := collection.UpdateOne(ctx, filter, update, options.Update().SetUpsert(true))
  201. if err != nil {
  202. return err
  203. }
  204. return nil
  205. }
  206. // 批量插入SIM卡日流量数据
  207. func UpdateSimCardBatchDayData(dataList []domain.SimCardDayData) (int64, error) {
  208. ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
  209. defer cancel()
  210. collection := database.GetCollection(CollectionName_SimCardMonthlyData)
  211. batchSize := 1000
  212. var totalInserted int64
  213. for start := 0; start < len(dataList); start += batchSize {
  214. end := start + batchSize
  215. if end > len(dataList) {
  216. end = len(dataList)
  217. }
  218. models := make([]mongo.WriteModel, 0, end-start)
  219. for _, doc := range dataList[start:end] {
  220. dailyUsageField := fmt.Sprintf("dailyUsage.%d", doc.Day)
  221. update := bson.M{
  222. "$set": bson.M{
  223. "allDataUsage": doc.AllDataUsage,
  224. "updateTime": doc.UpdateTime,
  225. dailyUsageField: doc.DailyUsage,
  226. },
  227. "$setOnInsert": bson.M{
  228. "simId": doc.SimId,
  229. "month": doc.Month,
  230. },
  231. }
  232. model := mongo.NewUpdateOneModel().
  233. SetFilter(bson.M{
  234. "simId": doc.SimId,
  235. "month": doc.Month,
  236. }).
  237. SetUpdate(update).
  238. SetUpsert(true)
  239. models = append(models, model)
  240. }
  241. result, err := collection.BulkWrite(
  242. ctx,
  243. models,
  244. options.BulkWrite().
  245. SetOrdered(false),
  246. )
  247. if err != nil {
  248. zap.L().Error("UpdateSimCardBatchMonthlyData bulk insert failed.", zap.String("err", err.Error()), zap.Int("start", start), zap.Int("end", end), zap.Int64("totalInserted", totalInserted))
  249. return totalInserted, fmt.Errorf(
  250. "bulk insert failed (%d~%d): %w",
  251. start,
  252. end,
  253. err,
  254. )
  255. }
  256. totalInserted += result.InsertedCount
  257. }
  258. return totalInserted, nil
  259. }