multi_deep.go 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. package main
  2. import (
  3. "fmt"
  4. "log"
  5. "strings"
  6. )
  7. // CheckLegalRelationshipsByStep 分层级判断企业名单之间是否存在投资关系
  8. func (c *NebulaClient) CheckLegalRelationshipsByStep(names []string, deep, stepLimit int) (bool, []string, error) {
  9. if len(names) < 2 {
  10. return false, nil, fmt.Errorf("企业数量不足,至少需要两个")
  11. }
  12. visited := make(map[string]bool)
  13. pathMap := map[string][]string{} // key: 路径key,value: 节点名称列表
  14. pathStrMap := map[string]string{} // key: 路径key,value: 形式化路径描述
  15. currentLayer := names // 当前要处理的起点
  16. startToTarget := make(map[string]struct{})
  17. for _, a := range names {
  18. for _, b := range names {
  19. if a != b {
  20. startToTarget[a+"->"+b] = struct{}{}
  21. }
  22. }
  23. }
  24. for totalStep := 1; totalStep <= deep; totalStep += stepLimit {
  25. thisStep := min(stepLimit, deep-totalStep+1)
  26. var nextLayer []string
  27. for _, start := range currentLayer {
  28. // 组装目标企业(排除自己)
  29. targets := []string{}
  30. for _, t := range names {
  31. if t != start {
  32. targets = append(targets, fmt.Sprintf(`%s`, t))
  33. }
  34. }
  35. targetList := strings.Join(targets, ", ")
  36. query := fmt.Sprintf(`
  37. USE %s;
  38. MATCH p=(a:Legal{name:"%s"})-[*1..%d]-(b:Legal)
  39. WHERE b.Legal.name IN [%s]
  40. RETURN p LIMIT 20
  41. `, Table_Space, start, thisStep, targetList)
  42. resp, err := c.ExecuteWithReconnect(query)
  43. if err != nil || resp == nil || !resp.IsSucceed() {
  44. log.Printf("查询失败: %v, %s\n", err, resp.GetErrorMsg())
  45. continue
  46. }
  47. for _, row := range resp.GetRows() {
  48. if len(row.Values) == 0 || !row.Values[0].IsSetPVal() {
  49. continue
  50. }
  51. path := row.Values[0].GetPVal()
  52. var namesInPath []string
  53. var builder strings.Builder
  54. // 起点
  55. src := path.Src
  56. startName := ""
  57. if src != nil && src.Vid != nil && src.Vid.IsSetSVal() {
  58. vid := string(src.Vid.GetSVal())
  59. lea, err := getLegalByVid(c.session, vid)
  60. if err == nil && lea != nil {
  61. startName = lea.Name
  62. }
  63. }
  64. namesInPath = append(namesInPath, startName)
  65. builder.WriteString(startName)
  66. // 步骤
  67. for _, step := range path.Steps {
  68. dstName := ""
  69. if step.Dst != nil && step.Dst.Vid != nil && step.Dst.Vid.IsSetSVal() {
  70. vid := string(step.Dst.Vid.GetSVal())
  71. lea, err := getLegalByVid(c.session, vid)
  72. if err == nil && lea != nil {
  73. dstName = lea.Name
  74. }
  75. }
  76. if step.Type > 0 {
  77. builder.WriteString(" → ")
  78. } else if step.Type < 0 {
  79. builder.WriteString(" ← ")
  80. } else {
  81. builder.WriteString(" - ")
  82. }
  83. builder.WriteString(dstName)
  84. namesInPath = append(namesInPath, dstName)
  85. }
  86. // 存储路径
  87. key := generatePathKey(namesInPath)
  88. pathMap[key] = namesInPath
  89. pathStrMap[key] = builder.String()
  90. // 记录下一层继续遍历
  91. last := namesInPath[len(namesInPath)-1]
  92. if !visited[last] && !isInList(names, last) {
  93. visited[last] = true
  94. nextLayer = append(nextLayer, last)
  95. }
  96. }
  97. }
  98. currentLayer = nextLayer
  99. }
  100. // 去重,保留最长路径
  101. finalMap := map[string]string{}
  102. for k1, nodes1 := range pathMap {
  103. shouldAdd := true
  104. for k2, nodes2 := range pathMap {
  105. if k1 == k2 {
  106. continue
  107. }
  108. if isSubPath(nodes1, nodes2) || isSubPath(reverseSlice(nodes1), nodes2) {
  109. shouldAdd = false
  110. break
  111. }
  112. }
  113. if shouldAdd {
  114. finalMap[k1] = pathStrMap[k1]
  115. }
  116. }
  117. if len(finalMap) > 0 {
  118. var result []string
  119. for _, v := range finalMap {
  120. result = append(result, v)
  121. }
  122. return true, result, nil
  123. }
  124. return false, nil, nil
  125. }
  126. func isInList(arr []string, target string) bool {
  127. for _, v := range arr {
  128. if v == target {
  129. return true
  130. }
  131. }
  132. return false
  133. }
  134. func min(a, b int) int {
  135. if a < b {
  136. return a
  137. }
  138. return b
  139. }