11package handler
22
33import (
4+ "fmt"
45 "net/http"
6+ "strings"
57 "time"
68
9+ "entgo.io/ent/dialect/sql"
710 "github.com/gin-gonic/gin"
811 "github.com/techbloghub/server/ent"
12+ "github.com/techbloghub/server/ent/company"
913 "github.com/techbloghub/server/ent/posting"
1014 "github.com/techbloghub/server/internal/common"
1115)
1216
13- type TitleSearchResponse struct {
17+ type PostingSearchResponse struct {
1418 ID int `json:"posting_id"`
1519 Title string `json:"title"`
1620 Url string `json:"url"`
@@ -23,73 +27,111 @@ type TitleSearchResponse struct {
2327}
2428
2529type PostingSearchResponses struct {
26- Count int `json:"count"`
27- Postings []TitleSearchResponse `json:"postings"`
28- HasNextPage bool `json:"has_next_page"`
30+ Count int `json:"count"`
31+ Postings []PostingSearchResponse `json:"postings"`
32+ HasNextPage bool `json:"has_next_page"`
2933}
3034
3135func GetPostings (client * ent.Client ) gin.HandlerFunc {
3236 return func (c * gin.Context ) {
3337 titleSearchParam := c .DefaultQuery ("title" , "" )
38+ tagsSearchParam := c .DefaultQuery ("tags" , "" )
3439 paging := common .GenerateTechPaging (c .Query ("cursor" ), c .Query ("size" ))
3540
36- totalCount , err := countTotalPostings (client , titleSearchParam , c )
41+ postings , err := fetchPostings (client , titleSearchParam , tagsSearchParam , paging , c )
3742 if err != nil {
3843 c .JSON (http .StatusInternalServerError , gin.H {"error" : err .Error ()})
3944 return
4045 }
4146
42- postings , err := fetchPostings (client , titleSearchParam , paging , c )
47+ totalCount , err := countPostings (client , titleSearchParam , tagsSearchParam , c )
4348 if err != nil {
4449 c .JSON (http .StatusInternalServerError , gin.H {"error" : err .Error ()})
4550 return
4651 }
4752
4853 c .JSON (http .StatusOK , PostingSearchResponses {
4954 Count : totalCount ,
50- Postings : convertToTitleSearchResponse (postings ),
55+ Postings : toPostingSearchResponses (postings ),
5156 HasNextPage : paging .HasNextPage (totalCount ),
5257 })
5358 }
5459}
5560
56- func fetchPostings (client * ent.Client , title string , paging common.TechbloghubPaging , c * gin.Context ) ([]* ent.Posting , error ) {
57- query := client .Posting .Query ().WithCompany ()
61+ func applySearchFilters (query * ent.PostingQuery , title , tags string ) * ent.PostingQuery {
5862 if title != "" {
5963 query = query .Where (posting .TitleContainsFold (title ))
6064 }
61- if paging .Cursor > 0 {
62- query = query .Where (posting .IDLT (paging .Cursor ))
65+ // 태그 조회 케이스 -> postgresql ARRAY 검색 형식에 맞춰야함
66+ // tags: [react,java]
67+ // query : where tags @> ARRAY['react','java']
68+ if tags != "" {
69+ arr := strings .Split (tags , "," )
70+ arrayQuery := "ARRAY" + fmt .Sprintf ("['%s']" , strings .Join (arr , "," ))
71+
72+ query = query .Where (func (s * sql.Selector ) {
73+ s .Where (sql .ExprP (fmt .Sprintf ("%s @> %s" , s .C ("tags" ), arrayQuery )))
74+ })
6375 }
6476
65- return query .Order (
66- ent .Desc (posting .FieldPublishedAt ),
67- ent .Desc (posting .FieldID ),
68- ).Limit (paging .Size ).All (c )
77+ return query
6978}
7079
71- func countTotalPostings (client * ent.Client , title string , c * gin.Context ) (int , error ) {
80+ func fetchPostings (client * ent.Client , title , tags string , paging common. TechbloghubPaging , c * gin.Context ) ([] * ent. Posting , error ) {
7281 query := client .Posting .Query ()
73- if title != "" {
74- query = query .Where (posting .TitleContainsFold (title ))
82+ query = applySearchFilters (query , title , tags )
83+
84+ if paging .Cursor > common .CURSOR_DEFAULT {
85+ query = query .Where (posting .IDLT (paging .Cursor ))
7586 }
87+
88+ return query .Where (posting .HasCompany ()).
89+ WithCompany (func (q * ent.CompanyQuery ) {
90+ q .Select (
91+ company .FieldLogoURL ,
92+ company .FieldName ,
93+ )
94+ }).
95+ Order (
96+ ent .Desc (posting .FieldPublishedAt ),
97+ ent .Desc (posting .FieldID ),
98+ ).
99+ Limit (paging .Size ).
100+ All (c .Request .Context ())
101+ }
102+
103+ func countPostings (client * ent.Client , title , tags string , c * gin.Context ) (int , error ) {
104+ query := client .Posting .Query ()
105+ query = applySearchFilters (query , title , tags )
76106 return query .Count (c )
77107}
78108
79- func convertToTitleSearchResponse (postings []* ent.Posting ) []TitleSearchResponse {
80- responses := make ([]TitleSearchResponse , len (postings ))
81- for i , posting := range postings {
82- responses [i ] = TitleSearchResponse {
109+ // 대체 왜 못갖고오냐!!!!
110+ func getCompanyInfo (posting * ent.Posting ) (string , string ) {
111+ if posting .Edges .Company != nil {
112+ return posting .Edges .Company .Name , posting .Edges .Company .LogoURL .String ()
113+ }
114+ return "Unknown" , ""
115+ }
116+
117+ func toPostingSearchResponses (postings []* ent.Posting ) []PostingSearchResponse {
118+ responses := make ([]PostingSearchResponse , len (postings ))
119+
120+ for _ , posting := range postings {
121+ companyName , logoURL := getCompanyInfo (posting )
122+
123+ responses = append (responses , PostingSearchResponse {
83124 ID : posting .ID ,
84125 Title : posting .Title ,
85126 Url : posting .URL .String (),
86- Company : posting . Edges . Company . Name ,
87- Logo : posting . Edges . Company . LogoURL . String () ,
127+ Company : companyName ,
128+ Logo : logoURL ,
88129 Tags : posting .Tags .ToStringSlice (),
89130 CreateTime : posting .CreateTime ,
90131 UpdateTime : posting .UpdateTime ,
91132 PublishedTime : posting .PublishedAt ,
92- }
133+ })
93134 }
135+
94136 return responses
95137}
0 commit comments