package quota import ( "app/commons/core" "app/commons/model/entity" "encoding/json" "github.com/demdxx/gocast" "github.com/samber/lo" "gorm.io/datatypes" "reflect" ) // 更新用户关系路径 -- 完成自测 func (s *Service) userParentIdsHandler() error { // 同步用户指标表与用户表pid关系 // 获取所有用户路径信息 type ParentInfo struct { Id int64 `json:"id"` ParentId int64 `json:"parentId"` ParentIds datatypes.JSON `json:"parentIds"` } var rows []ParentInfo err := s.DB().Model(&entity.User{}). Select("id,parent_id,parent_ids").Scan(&rows).Error if err != nil { return err } idPidMap := make(map[int64]int64) for _, row := range rows { idPidMap[row.Id] = row.ParentId } type QuotaInfo struct { UserId int64 `json:"userId"` ParentId int64 `json:"parentId"` } var quotas []QuotaInfo err = s.DB().Model(&entity.UserQuota{}). Select("user_id,parent_id").Scan("as).Error if err != nil { return err } quotaIdMap := make(map[int64]int64) for _, item := range quotas { quotaIdMap[item.UserId] = item.ParentId } count := len(rows) for i, row := range rows { if (i+1)%2000 == 0 { core.JobLog.Infof("用户更新 ParentIds 进度:%d/%d", i+1, count) } quotaPid, ok := quotaIdMap[row.Id] if !ok { continue } // tips: 如果当前上级id 与 指标用户上级ID不一致则进行修复 if row.ParentId != quotaPid { err = s.DB().Model(&entity.UserQuota{}). Where("user_id", row.Id). Updates(map[string]interface{}{ "parent_id": row.ParentId, }).Error if err != nil { return err } } ids := make([]int64, 0) if len(row.ParentIds) > 0 { if err := json.Unmarshal(row.ParentIds, &ids); err != nil { core.JobLog.Infof("json.Unmarshal:%s", err.Error()) continue } } path := make([]int64, 0) var uid int64 // 当前用户ID var pid int64 // 当前上级ID pid = row.ParentId uid = row.Id if pid == 0 { if len(ids) == 0 { continue } jsonData, err := json.Marshal(path) if err != nil { return err } core.JobLog.Infof("原路径:%+v 新路径:%+v", ids, []int64{}) err = s.DB().Model(&entity.User{}). Where("id", uid). Updates(map[string]interface{}{ "parent_ids": jsonData, }).Error if err != nil { return err } continue } // 上级不存在则跳过 同时 路径发生了变化则修改 // 遍历找出上级 for { path = append(path, pid) // 通过映射查找出 当前上级ID value, exists := idPidMap[pid] if !exists { break } if value == 0 { break } // 防止死循环 if lo.Contains(path, value) { break } uid = pid pid = gocast.ToInt64(value) } // 可优化为原生批量修改 if !reflect.DeepEqual(ids, path) { jsonData, err := json.Marshal(path) if err != nil { return err } core.JobLog.Infof("原路径:%+v 新路径:%+v", ids, path) err = s.DB().Model(&entity.User{}). Where("id", row.Id). Updates(map[string]interface{}{ "parent_ids": jsonData, }).Error if err != nil { return err } } } core.JobLog.Infof("更新所有用户PATH 用户总数:%d 信息完成", count) return nil }