You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

search.go 21 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653
  1. package routers
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "strconv"
  6. "strings"
  7. "code.gitea.io/gitea/models"
  8. "code.gitea.io/gitea/modules/context"
  9. "code.gitea.io/gitea/modules/log"
  10. "code.gitea.io/gitea/modules/setting"
  11. "github.com/olivere/elastic/v7"
  12. )
  13. type SearchRes struct {
  14. Total int64
  15. Result []map[string]interface{}
  16. }
  17. var client *elastic.Client
  18. func InitESClient() {
  19. ESSearchUrl := setting.ESSearchURL
  20. var err error
  21. client, err = elastic.NewClient(elastic.SetSniff(false), elastic.SetURL(ESSearchUrl))
  22. if err != nil {
  23. log.Info("es init error.")
  24. //panic(err)
  25. }
  26. }
  27. func Search(ctx *context.Context) {
  28. keyword := strings.Trim(ctx.Query("q"), " ")
  29. ctx.Data["Keyword"] = keyword
  30. ctx.Data["SortType"] = "newest"
  31. ctx.HTML(200, "explore/search_new")
  32. }
  33. func SearchApi(ctx *context.Context) {
  34. TableName := ctx.Query("TableName")
  35. Key := ctx.Query("Key")
  36. Page := ctx.QueryInt("Page")
  37. PageSize := ctx.QueryInt("PageSize")
  38. OnlyReturnNum := ctx.QueryBool("OnlyReturnNum")
  39. OnlySearchLabel := ctx.QueryBool("OnlySearchLabel")
  40. if Page <= 0 {
  41. Page = 1
  42. }
  43. if PageSize <= 0 || PageSize > 200 {
  44. PageSize = setting.UI.IssuePagingNum
  45. }
  46. if TableName == "repository" {
  47. if OnlySearchLabel {
  48. searchRepoByLabel(ctx, Key, Page, PageSize)
  49. } else {
  50. searchRepo(ctx, "repository-es-index", Key, Page, PageSize, OnlyReturnNum)
  51. }
  52. return
  53. } else if TableName == "issue" {
  54. searchIssue(ctx, "issue-es-index", Key, Page, PageSize, OnlyReturnNum)
  55. return
  56. } else if TableName == "user" {
  57. searchUserOrOrg(ctx, "user-es-index", Key, Page, PageSize, true, OnlyReturnNum)
  58. return
  59. } else if TableName == "org" {
  60. searchUserOrOrg(ctx, "user-es-index", Key, Page, PageSize, false, OnlyReturnNum)
  61. return
  62. } else if TableName == "dataset" {
  63. searchDataSet(ctx, "dataset-es-index", Key, Page, PageSize, OnlyReturnNum)
  64. return
  65. } else if TableName == "pr" {
  66. searchPR(ctx, "issue-es-index", Key, Page, PageSize, OnlyReturnNum)
  67. return
  68. }
  69. }
  70. func searchRepoByLabel(ctx *context.Context, Key string, Page int, PageSize int) {
  71. /*
  72. 项目, ES名称: repository-es-index
  73. 搜索:
  74. name character varying(255) , 项目名称
  75. description text, 项目描述
  76. topics json, 标签
  77. 排序:
  78. updated_unix
  79. num_watches,
  80. num_stars,
  81. num_forks,
  82. */
  83. SortBy := ctx.Query("SortBy")
  84. if SortBy == "" {
  85. SortBy = "updated_unix.keyword"
  86. }
  87. ascending := ctx.QueryBool("Ascending")
  88. log.Info("query searchRepoByLabel start")
  89. if Key != "" {
  90. boolQ := elastic.NewBoolQuery()
  91. topicsQuery := elastic.NewMatchQuery("topics", Key)
  92. boolQ.Should(topicsQuery)
  93. res, err := client.Search("repository-es-index").Query(boolQ).SortBy(elastic.NewScoreSort(), elastic.NewFieldSort(SortBy).Order(ascending)).From((Page - 1) * PageSize).Size(PageSize).Highlight(queryHighlight("topics")).Do(ctx.Req.Context())
  94. if err == nil {
  95. searchJson, _ := json.Marshal(res)
  96. log.Info("searchJson=" + string(searchJson))
  97. result := makeRepoResult(res, "", false)
  98. ctx.JSON(200, result)
  99. } else {
  100. log.Info("query es error," + err.Error())
  101. ctx.JSON(200, "")
  102. }
  103. } else {
  104. ctx.JSON(200, "")
  105. }
  106. }
  107. func searchRepo(ctx *context.Context, TableName string, Key string, Page int, PageSize int, OnlyReturnNum bool) {
  108. /*
  109. 项目, ES名称: repository-es-index
  110. 搜索:
  111. name character varying(255) , 项目名称
  112. description text, 项目描述
  113. topics json, 标签
  114. 排序:
  115. updated_unix
  116. num_watches,
  117. num_stars,
  118. num_forks,
  119. */
  120. SortBy := ctx.Query("SortBy")
  121. if SortBy == "" {
  122. SortBy = "updated_unix.keyword"
  123. }
  124. ascending := ctx.QueryBool("Ascending")
  125. log.Info("query searchRepo start")
  126. if Key != "" {
  127. boolQ := elastic.NewBoolQuery()
  128. nameQuery := elastic.NewMatchQuery("name", Key).Boost(1024).QueryName("f_first")
  129. descriptionQuery := elastic.NewMatchQuery("description", Key).Boost(1.5).QueryName("f_second")
  130. topicsQuery := elastic.NewMatchQuery("topics", Key).Boost(1).QueryName("f_third")
  131. boolQ.Should(nameQuery, descriptionQuery, topicsQuery)
  132. res, err := client.Search(TableName).Query(boolQ).SortBy(elastic.NewScoreSort(), elastic.NewFieldSort(SortBy).Order(ascending)).From((Page - 1) * PageSize).Size(PageSize).Highlight(queryHighlight("name", "description", "topics")).Do(ctx.Req.Context())
  133. if err == nil {
  134. searchJson, _ := json.Marshal(res)
  135. log.Info("searchJson=" + string(searchJson))
  136. result := makeRepoResult(res, Key, OnlyReturnNum)
  137. ctx.JSON(200, result)
  138. } else {
  139. log.Info("query es error," + err.Error())
  140. ctx.JSON(200, "")
  141. }
  142. } else {
  143. log.Info("query all content.")
  144. //搜索的属性要指定{"timestamp":{"unmapped_type":"date"}}
  145. res, err := client.Search(TableName).SortBy(elastic.NewFieldSort(SortBy).Order(ascending)).From((Page - 1) * PageSize).Size(PageSize).Do(ctx.Req.Context())
  146. if err == nil {
  147. searchJson, _ := json.Marshal(res)
  148. log.Info("searchJson=" + string(searchJson))
  149. result := makeRepoResult(res, "", OnlyReturnNum)
  150. ctx.JSON(200, result)
  151. } else {
  152. log.Info("query es error," + err.Error())
  153. ctx.JSON(200, "")
  154. }
  155. }
  156. }
  157. func makeRepoResult(sRes *elastic.SearchResult, Key string, OnlyReturnNum bool) *SearchRes {
  158. total := sRes.Hits.TotalHits.Value
  159. result := make([]map[string]interface{}, 0)
  160. if !OnlyReturnNum {
  161. for i, hit := range sRes.Hits.Hits {
  162. log.Info("this is repo query " + fmt.Sprint(i) + " result.")
  163. recordSource := make(map[string]interface{})
  164. source, err := hit.Source.MarshalJSON()
  165. if err == nil {
  166. err = json.Unmarshal(source, &recordSource)
  167. if err == nil {
  168. record := make(map[string]interface{})
  169. record["id"] = hit.Id
  170. record["name"] = getLabelValue("name", recordSource, hit.Highlight)
  171. record["real_name"] = recordSource["name"]
  172. record["owner_name"] = recordSource["owner_name"]
  173. if recordSource["description"] != nil {
  174. desc := getLabelValue("description", recordSource, hit.Highlight)
  175. record["description"] = dealLongText(desc, Key, hit.MatchedQueries)
  176. } else {
  177. record["description"] = ""
  178. }
  179. if Key == "" {
  180. record["hightTopics"] = getLabelValue("topics", recordSource, hit.Highlight)
  181. }
  182. record["num_watches"] = recordSource["num_watches"]
  183. record["num_stars"] = recordSource["num_stars"]
  184. record["num_forks"] = recordSource["num_forks"]
  185. if recordSource["topics"] != nil {
  186. topicsStr := recordSource["topics"].(string)
  187. log.Info("topicsStr=" + topicsStr)
  188. if topicsStr != "null" {
  189. topicsStr = strings.Replace(topicsStr, "\"", "", -1)
  190. topicsStr = topicsStr[1 : len(topicsStr)-1]
  191. log.Info("record[\"topics\"]=" + topicsStr)
  192. topicstmp := strings.Split(topicsStr, ",")
  193. record["topics"] = topicstmp
  194. }
  195. }
  196. if recordSource["avatar"] != nil {
  197. record["avatar"] = setting.AppSubURL + "/repo-avatars/" + recordSource["avatar"].(string)
  198. }
  199. record["updated_unix"] = recordSource["updated_unix"]
  200. record["lang"] = recordSource["lang"]
  201. result = append(result, record)
  202. } else {
  203. log.Info("deal repo source error," + err.Error())
  204. }
  205. } else {
  206. log.Info("deal repo source error," + err.Error())
  207. }
  208. }
  209. }
  210. returnObj := &SearchRes{
  211. Total: total,
  212. Result: result,
  213. }
  214. return returnObj
  215. }
  216. func dealLongText(text string, Key string, MatchedQueries []string) string {
  217. var isNeedToDealText bool
  218. isNeedToDealText = false
  219. if len(MatchedQueries) > 0 && Key != "" {
  220. if MatchedQueries[0] == "f_second" || MatchedQueries[0] == "f_third" {
  221. isNeedToDealText = true
  222. }
  223. }
  224. stringlen := len(text)
  225. if isNeedToDealText && stringlen > 200 {
  226. index := strings.Index(text, Key)
  227. if index > 0 {
  228. start := index - 50
  229. if start < 0 {
  230. start = 0
  231. }
  232. end := index + 150
  233. if end >= stringlen {
  234. end = stringlen
  235. }
  236. return text[start:end]
  237. } else {
  238. return text[0:200]
  239. }
  240. } else {
  241. if stringlen > 200 {
  242. return text[0:200]
  243. } else {
  244. return text
  245. }
  246. }
  247. }
  248. func searchUserOrOrg(ctx *context.Context, TableName string, Key string, Page int, PageSize int, IsQueryUser bool, OnlyReturnNum bool) {
  249. /*
  250. 用户或者组织 ES名称: user-es-index
  251. 搜索:
  252. name , 名称
  253. full_name 全名
  254. description 描述或者简介
  255. 排序:
  256. created_unix
  257. 名称字母序
  258. */
  259. SortBy := ctx.Query("SortBy")
  260. if SortBy == "" {
  261. SortBy = "created_unix.keyword"
  262. }
  263. ascending := ctx.QueryBool("Ascending")
  264. boolQ := elastic.NewBoolQuery()
  265. typeValue := 1
  266. if IsQueryUser {
  267. typeValue = 0
  268. }
  269. UserOrOrgQuery := elastic.NewTermQuery("type", typeValue)
  270. if Key != "" {
  271. boolKeyQ := elastic.NewBoolQuery()
  272. log.Info("issue Key=" + Key)
  273. nameQuery := elastic.NewMatchQuery("name", Key).Boost(2).QueryName("f_first")
  274. full_nameQuery := elastic.NewMatchQuery("full_name", Key).Boost(1.5).QueryName("f_second")
  275. descriptionQuery := elastic.NewMatchQuery("description", Key).Boost(1).QueryName("f_third")
  276. boolKeyQ.Should(nameQuery, full_nameQuery, descriptionQuery)
  277. boolQ.Must(UserOrOrgQuery, boolKeyQ)
  278. } else {
  279. boolQ.Must(UserOrOrgQuery)
  280. }
  281. res, err := client.Search(TableName).Query(boolQ).Sort(SortBy, ascending).From((Page - 1) * PageSize).Size(PageSize).Highlight(queryHighlight("name", "full_name", "description")).Do(ctx.Req.Context())
  282. if err == nil {
  283. searchJson, _ := json.Marshal(res)
  284. log.Info("searchJson=" + string(searchJson))
  285. result := makeUserOrOrgResult(res, Key, ctx, OnlyReturnNum)
  286. ctx.JSON(200, result)
  287. } else {
  288. log.Info("query es error," + err.Error())
  289. ctx.JSON(200, "")
  290. }
  291. }
  292. func getLabelValue(key string, recordSource map[string]interface{}, searchHighliht elastic.SearchHitHighlight) string {
  293. if value, ok := searchHighliht[key]; !ok {
  294. if recordSource[key] != nil {
  295. return recordSource[key].(string)
  296. } else {
  297. return ""
  298. }
  299. } else {
  300. return value[0]
  301. }
  302. }
  303. func makeUserOrOrgResult(sRes *elastic.SearchResult, Key string, ctx *context.Context, OnlyReturnNum bool) *SearchRes {
  304. total := sRes.Hits.TotalHits.Value
  305. result := make([]map[string]interface{}, 0)
  306. if !OnlyReturnNum {
  307. for i, hit := range sRes.Hits.Hits {
  308. log.Info("this is user query " + fmt.Sprint(i) + " result.")
  309. recordSource := make(map[string]interface{})
  310. source, err := hit.Source.MarshalJSON()
  311. if err == nil {
  312. err = json.Unmarshal(source, &recordSource)
  313. if err == nil {
  314. record := make(map[string]interface{})
  315. record["id"] = hit.Id
  316. record["name"] = getLabelValue("name", recordSource, hit.Highlight)
  317. record["real_name"] = recordSource["name"]
  318. record["full_name"] = getLabelValue("full_name", recordSource, hit.Highlight)
  319. if recordSource["description"] != nil {
  320. desc := getLabelValue("description", recordSource, hit.Highlight)
  321. record["description"] = dealLongText(desc, Key, hit.MatchedQueries)
  322. } else {
  323. record["description"] = ""
  324. }
  325. if ctx.User != nil {
  326. record["email"] = recordSource["email"]
  327. } else {
  328. record["email"] = ""
  329. }
  330. record["location"] = recordSource["location"]
  331. record["website"] = recordSource["website"]
  332. record["num_repos"] = recordSource["num_repos"]
  333. record["num_teams"] = recordSource["num_teams"]
  334. record["num_members"] = recordSource["num_members"]
  335. record["avatar"] = strings.TrimRight(setting.AppSubURL, "/") + "/user/avatar/" + recordSource["name"].(string) + "/" + strconv.Itoa(-1)
  336. record["updated_unix"] = recordSource["updated_unix"]
  337. record["created_unix"] = recordSource["created_unix"]
  338. result = append(result, record)
  339. } else {
  340. log.Info("deal user source error," + err.Error())
  341. }
  342. } else {
  343. log.Info("deal user source error," + err.Error())
  344. }
  345. }
  346. }
  347. returnObj := &SearchRes{
  348. Total: total,
  349. Result: result,
  350. }
  351. return returnObj
  352. }
  353. func searchDataSet(ctx *context.Context, TableName string, Key string, Page int, PageSize int, OnlyReturnNum bool) {
  354. /*
  355. 数据集,ES名称:dataset-es-index
  356. 搜索:
  357. title , 名称
  358. description 描述
  359. category 标签
  360. file_name 数据集文件名称
  361. 排序:
  362. download_times
  363. */
  364. SortBy := ctx.Query("SortBy")
  365. if SortBy == "" {
  366. SortBy = "download_times.keyword"
  367. }
  368. ascending := ctx.QueryBool("Ascending")
  369. log.Info("query searchRepo start")
  370. boolQ := elastic.NewBoolQuery()
  371. if Key != "" {
  372. nameQuery := elastic.NewMatchQuery("title", Key).Boost(2).QueryName("f_first")
  373. descQuery := elastic.NewMatchQuery("description", Key).Boost(1.5).QueryName("f_second")
  374. fileNameQuery := elastic.NewMatchQuery("file_name", Key).Boost(1).QueryName("f_third")
  375. categoryQuery := elastic.NewMatchQuery("category", Key).Boost(1).QueryName("f_fourth")
  376. boolQ.Should(nameQuery, descQuery, categoryQuery, fileNameQuery)
  377. res, err := client.Search(TableName).Query(boolQ).Sort(SortBy, ascending).From((Page - 1) * PageSize).Size(PageSize).Highlight(queryHighlight("title", "description", "file_name", "category")).Do(ctx.Req.Context())
  378. if err == nil {
  379. searchJson, _ := json.Marshal(res)
  380. log.Info("searchJson=" + string(searchJson))
  381. result := makeDatasetResult(res, Key, OnlyReturnNum)
  382. ctx.JSON(200, result)
  383. } else {
  384. log.Info("query es error," + err.Error())
  385. }
  386. } else {
  387. log.Info("query all content.")
  388. //搜索的属性要指定{"timestamp":{"unmapped_type":"date"}}
  389. res, err := client.Search(TableName).Sort(SortBy, ascending).From((Page - 1) * PageSize).Size(PageSize).Do(ctx.Req.Context())
  390. if err == nil {
  391. searchJson, _ := json.Marshal(res)
  392. log.Info("searchJson=" + string(searchJson))
  393. result := makeDatasetResult(res, "", OnlyReturnNum)
  394. ctx.JSON(200, result)
  395. } else {
  396. log.Info("query es error," + err.Error())
  397. ctx.JSON(200, "")
  398. }
  399. }
  400. }
  401. func makeDatasetResult(sRes *elastic.SearchResult, Key string, OnlyReturnNum bool) *SearchRes {
  402. total := sRes.Hits.TotalHits.Value
  403. result := make([]map[string]interface{}, 0)
  404. if !OnlyReturnNum {
  405. for i, hit := range sRes.Hits.Hits {
  406. log.Info("this is dataset query " + fmt.Sprint(i) + " result.")
  407. recordSource := make(map[string]interface{})
  408. source, err := hit.Source.MarshalJSON()
  409. if err == nil {
  410. err = json.Unmarshal(source, &recordSource)
  411. if err == nil {
  412. record := make(map[string]interface{})
  413. record["id"] = hit.Id
  414. userIdStr := recordSource["user_id"].(string)
  415. userId, cerr := strconv.ParseInt(userIdStr, 10, 64)
  416. if cerr == nil {
  417. user, errUser := models.GetUserByID(userId)
  418. if errUser == nil {
  419. record["owerName"] = user.GetDisplayName()
  420. record["avatar"] = user.RelAvatarLink()
  421. }
  422. }
  423. setRepoInfo(recordSource, record)
  424. record["title"] = getLabelValue("title", recordSource, hit.Highlight)
  425. record["category"] = getLabelValue("category", recordSource, hit.Highlight)
  426. if recordSource["description"] != nil {
  427. desc := getLabelValue("description", recordSource, hit.Highlight)
  428. record["description"] = dealLongText(desc, Key, hit.MatchedQueries)
  429. } else {
  430. record["description"] = ""
  431. }
  432. record["file_name"] = recordSource["file_name"]
  433. record["task"] = recordSource["task"]
  434. record["download_times"] = recordSource["download_times"]
  435. record["created_unix"] = recordSource["created_unix"]
  436. result = append(result, record)
  437. } else {
  438. log.Info("deal dataset source error," + err.Error())
  439. }
  440. } else {
  441. log.Info("deal dataset source error," + err.Error())
  442. }
  443. }
  444. }
  445. returnObj := &SearchRes{
  446. Total: total,
  447. Result: result,
  448. }
  449. return returnObj
  450. }
  451. func searchIssue(ctx *context.Context, TableName string, Key string, Page int, PageSize int, OnlyReturnNum bool) {
  452. /*
  453. 任务,合并请求 ES名称:issue-es-index
  454. 搜索:
  455. name character varying(255) , 标题
  456. content text, 内容
  457. comment text, 评论
  458. 排序:
  459. updated_unix
  460. */
  461. SortBy := ctx.Query("SortBy")
  462. if SortBy == "" {
  463. SortBy = "updated_unix.keyword"
  464. }
  465. ascending := ctx.QueryBool("Ascending")
  466. boolQ := elastic.NewBoolQuery()
  467. isIssueQuery := elastic.NewTermQuery("is_pull", "f")
  468. if Key != "" {
  469. boolKeyQ := elastic.NewBoolQuery()
  470. log.Info("issue Key=" + Key)
  471. nameQuery := elastic.NewMatchQuery("name", Key).Boost(2).QueryName("f_first")
  472. contentQuery := elastic.NewMatchQuery("content", Key).Boost(1.5).QueryName("f_second")
  473. commentQuery := elastic.NewMatchQuery("comment", Key).Boost(1).QueryName("f_third")
  474. boolKeyQ.Should(nameQuery, contentQuery, commentQuery)
  475. boolQ.Must(isIssueQuery, boolKeyQ)
  476. } else {
  477. boolQ.Must(isIssueQuery)
  478. }
  479. res, err := client.Search(TableName).Query(boolQ).Sort(SortBy, ascending).From((Page - 1) * PageSize).Size(PageSize).Highlight(queryHighlight("name", "content", "comment")).Do(ctx.Req.Context())
  480. if err == nil {
  481. searchJson, _ := json.Marshal(res)
  482. log.Info("searchJson=" + string(searchJson))
  483. result := makeIssueResult(res, Key, OnlyReturnNum)
  484. ctx.JSON(200, result)
  485. } else {
  486. log.Info("query es error," + err.Error())
  487. }
  488. }
  489. func queryHighlight(names ...string) *elastic.Highlight {
  490. re := elastic.NewHighlight()
  491. for i := 0; i < len(names); i++ {
  492. field := &elastic.HighlighterField{
  493. Name: names[i],
  494. }
  495. re.Fields(field)
  496. }
  497. re.PreTags("<font color='red'>")
  498. re.PostTags("</font>")
  499. return re
  500. }
  501. func setRepoInfo(recordSource map[string]interface{}, record map[string]interface{}) {
  502. repoIdstr := recordSource["repo_id"].(string)
  503. repoId, cerr := strconv.ParseInt(repoIdstr, 10, 64)
  504. if cerr == nil {
  505. repo, errRepo := models.GetRepositoryByID(repoId)
  506. if errRepo == nil {
  507. log.Info("repo_url=" + repo.FullName())
  508. record["repoUrl"] = repo.FullName()
  509. record["avatar"] = repo.RelAvatarLink()
  510. } else {
  511. log.Info("repo err=" + errRepo.Error())
  512. }
  513. } else {
  514. log.Info("parse int err=" + cerr.Error())
  515. }
  516. }
  517. func makeIssueResult(sRes *elastic.SearchResult, Key string, OnlyReturnNum bool) *SearchRes {
  518. total := sRes.Hits.TotalHits.Value
  519. result := make([]map[string]interface{}, 0)
  520. if !OnlyReturnNum {
  521. for i, hit := range sRes.Hits.Hits {
  522. log.Info("this is issue query " + fmt.Sprint(i) + " result.")
  523. recordSource := make(map[string]interface{})
  524. source, err := hit.Source.MarshalJSON()
  525. if err == nil {
  526. err = json.Unmarshal(source, &recordSource)
  527. if err == nil {
  528. record := make(map[string]interface{})
  529. record["id"] = hit.Id
  530. record["repo_id"] = recordSource["repo_id"]
  531. log.Info("recordSource[\"repo_id\"]=" + fmt.Sprint(recordSource["repo_id"]))
  532. setRepoInfo(recordSource, record)
  533. record["name"] = getLabelValue("name", recordSource, hit.Highlight)
  534. if recordSource["content"] != nil {
  535. desc := getLabelValue("content", recordSource, hit.Highlight)
  536. record["content"] = dealLongText(desc, Key, hit.MatchedQueries)
  537. if _, ok := hit.Highlight["content"]; !ok {
  538. if _, ok_comment := hit.Highlight["comment"]; ok_comment {
  539. desc := getLabelValue("comment", recordSource, hit.Highlight)
  540. record["content"] = dealLongText(desc, Key, hit.MatchedQueries)
  541. }
  542. }
  543. } else {
  544. if recordSource["comment"] != nil {
  545. desc := getLabelValue("comment", recordSource, hit.Highlight)
  546. record["content"] = dealLongText(desc, Key, hit.MatchedQueries)
  547. }
  548. }
  549. if recordSource["pr_id"] != nil {
  550. record["pr_id"] = recordSource["pr_id"]
  551. }
  552. record["num_comments"] = recordSource["num_comments"]
  553. record["is_closed"] = recordSource["is_closed"]
  554. record["updated_unix"] = recordSource["updated_unix"]
  555. result = append(result, record)
  556. } else {
  557. log.Info("deal issue source error," + err.Error())
  558. }
  559. } else {
  560. log.Info("deal issue source error," + err.Error())
  561. }
  562. }
  563. }
  564. returnObj := &SearchRes{
  565. Total: total,
  566. Result: result,
  567. }
  568. return returnObj
  569. }
  570. func searchPR(ctx *context.Context, TableName string, Key string, Page int, PageSize int, OnlyReturnNum bool) {
  571. /*
  572. 任务,合并请求 ES名称:issue-es-index
  573. 搜索:
  574. name character varying(255) , 标题
  575. content text, 内容
  576. comment text, 评论
  577. 排序:
  578. updated_unix
  579. */
  580. SortBy := ctx.Query("SortBy")
  581. if SortBy == "" {
  582. SortBy = "updated_unix.keyword"
  583. }
  584. ascending := ctx.QueryBool("Ascending")
  585. boolQ := elastic.NewBoolQuery()
  586. isPRQuery := elastic.NewTermQuery("is_pull", "t")
  587. if Key != "" {
  588. boolKeyQ := elastic.NewBoolQuery()
  589. log.Info("issue Key=" + Key)
  590. nameQuery := elastic.NewMatchQuery("name", Key).Boost(2).QueryName("f_first")
  591. contentQuery := elastic.NewMatchQuery("content", Key).Boost(1.5).QueryName("f_second")
  592. commentQuery := elastic.NewMatchQuery("comment", Key).Boost(1).QueryName("f_third")
  593. boolKeyQ.Should(nameQuery, contentQuery, commentQuery)
  594. boolQ.Must(isPRQuery, boolKeyQ)
  595. } else {
  596. boolQ.Must(isPRQuery)
  597. }
  598. res, err := client.Search(TableName).Query(boolQ).Sort(SortBy, ascending).From((Page - 1) * PageSize).Size(PageSize).Highlight(queryHighlight("name", "content", "comment")).Do(ctx.Req.Context())
  599. if err == nil {
  600. result := makeIssueResult(res, Key, OnlyReturnNum)
  601. ctx.JSON(200, result)
  602. } else {
  603. log.Info("query es error," + err.Error())
  604. }
  605. }