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

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