bidding_count.go 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. package main
  2. import (
  3. "context"
  4. "fmt"
  5. "github.com/xuri/excelize/v2"
  6. "go.mongodb.org/mongo-driver/bson"
  7. "go.mongodb.org/mongo-driver/mongo"
  8. "go.mongodb.org/mongo-driver/mongo/options"
  9. "log"
  10. "strings"
  11. )
  12. // MongoDB 配置
  13. const (
  14. mongoHost = "172.31.31.202:27081,172.20.45.128:27080" // MongoDB 地址(可修改)
  15. mongoUser = "SJZY_RWbid_ES" // MongoDB 用户名(替换为你的用户名)
  16. mongoPassword = "SJZY@B4i4D5e6S" // MongoDB 密码(替换为你的密码)
  17. mongoDatabase = "qfw" // 目标数据库(替换为你的数据库名称)
  18. mongoCollection = "bidding" // MongoDB 表(集合)
  19. authSource = "admin" // 认证数据库(通常是 admin)
  20. )
  21. // 2024 年的 UNIX 时间戳范围
  22. const (
  23. startOf2024 = 1704067200 // 2024-01-01 00:00:00
  24. endOf2024 = 1735689599 // 2024-12-31 23:59:59
  25. //endOf2024 = 1704384000 // 2024-02-01 23:59:59
  26. )
  27. // 连接 MongoDB(带用户名密码)
  28. func connectMongoDB() (*mongo.Client, error) {
  29. credential := options.Credential{
  30. Username: mongoUser,
  31. Password: mongoPassword,
  32. AuthSource: authSource,
  33. }
  34. clientOptions := options.Client().ApplyURI("mongodb://" + mongoHost).SetAuth(credential)
  35. client, err := mongo.Connect(context.TODO(), clientOptions)
  36. if err != nil {
  37. return nil, err
  38. }
  39. // 测试连接
  40. err = client.Ping(context.TODO(), nil)
  41. if err != nil {
  42. return nil, err
  43. }
  44. fmt.Println("✅ MongoDB 连接成功!")
  45. return client, nil
  46. }
  47. // 计数结果结构体
  48. type CountResult struct {
  49. toptypeCount int
  50. subtypeCount int
  51. }
  52. func processExcel() {
  53. filePath := "银行业金融机构法人名单.xlsx"
  54. // 1. 读取 Excel(获取 A 列数据)
  55. f, err := excelize.OpenFile(filePath)
  56. if err != nil {
  57. log.Fatal("❌ 无法打开 Excel 文件:", err)
  58. }
  59. defer f.Close()
  60. // 2. 解析机构名称(A 列)到 map
  61. buyerMap := make(map[string]int) // 用于快速匹配
  62. rowIndexMap := make(map[string]int) // 记录 buyerName 对应的 Excel 行号
  63. rows, err := f.GetRows("Sheet3")
  64. if err != nil {
  65. log.Fatal("❌ 无法读取 Sheet3:", err)
  66. }
  67. for i, row := range rows {
  68. if i == 0 || len(row) == 0 {
  69. continue // 跳过表头或空行
  70. }
  71. buyerName := row[0]
  72. if buyerName != "" {
  73. buyerMap[buyerName] = i + 1 // 记录 buyerName 在 Excel 的行号(从 1 开始)
  74. rowIndexMap[buyerName] = i + 1
  75. }
  76. }
  77. // 3. 连接 MongoDB
  78. client, err := connectMongoDB()
  79. if err != nil {
  80. log.Fatal("❌ MongoDB 连接失败:", err)
  81. }
  82. defer client.Disconnect(context.TODO())
  83. collection := client.Database(mongoDatabase).Collection(mongoCollection)
  84. // 4. **遍历 MongoDB 数据(逐条处理)**
  85. countResults := processBiddingData(collection, buyerMap)
  86. // 5. **批量更新 Excel**
  87. for buyerName, result := range countResults {
  88. rowIdx := rowIndexMap[buyerName]
  89. f.SetCellInt("Sheet3", fmt.Sprintf("B%d", rowIdx), result.toptypeCount)
  90. f.SetCellInt("Sheet3", fmt.Sprintf("C%d", rowIdx), result.subtypeCount)
  91. }
  92. // 6. 保存 Excel
  93. if err := f.SaveAs(filePath); err != nil {
  94. log.Fatal("❌ 保存 Excel 失败:", err)
  95. }
  96. fmt.Println("✅ 统计完成,数据已更新到 Excel!")
  97. }
  98. // 逐条处理 MongoDB 数据,统计 `buyer` 匹配情况
  99. func processBiddingData(collection *mongo.Collection, buyerMap map[string]int) map[string]CountResult {
  100. countResults := make(map[string]CountResult)
  101. // 1. 查询符合 `publishtime` 条件的数据
  102. filter := bson.M{
  103. "publishtime": bson.M{"$gte": startOf2024, "$lte": endOf2024},
  104. //"extracttype": bson.M{"$ne": -1}, // 过滤掉 `extracttype = -1` 的数据
  105. }
  106. opts := options.Find().SetProjection(bson.M{"buyer": 1, "toptype": 1, "publishtime": 1, "subtype": 1, "extracttype": 1})
  107. cursor, err := collection.Find(context.TODO(), filter, opts)
  108. if err != nil {
  109. log.Fatal("❌ MongoDB 查询失败:", err)
  110. }
  111. defer cursor.Close(context.TODO())
  112. st := 0
  113. // 2. **逐条处理数据**
  114. for cursor.Next(context.TODO()) {
  115. var record struct {
  116. Buyer string `bson:"buyer"`
  117. Toptype string `bson:"toptype"`
  118. Subtype string `bson:"subtype"`
  119. Extracttype int `bson:"extracttype"`
  120. Publishtime int `bson:"publishtime"`
  121. }
  122. if err := cursor.Decode(&record); err != nil {
  123. log.Println("⚠ 解析 MongoDB 数据失败:", err)
  124. continue
  125. }
  126. if record.Extracttype < 0 {
  127. continue
  128. }
  129. if st%1000 == 0 {
  130. log.Println("stststsstststststtst", st, record.Buyer, record.Publishtime)
  131. }
  132. st++
  133. // 3. **在 Go 代码中匹配 `buyer`**
  134. for buyerName := range buyerMap {
  135. if strings.Contains(record.Buyer, buyerName) {
  136. result := countResults[buyerName]
  137. if record.Toptype == "招标" || record.Toptype == "结果" {
  138. result.toptypeCount++
  139. }
  140. if record.Subtype == "合同" {
  141. result.subtypeCount++
  142. }
  143. countResults[buyerName] = result
  144. }
  145. }
  146. }
  147. if err := cursor.Err(); err != nil {
  148. log.Fatal("❌ MongoDB 游标遍历错误:", err)
  149. }
  150. return countResults
  151. }