I'm writing a controller for GetPosts request using gorm and its raw SQL builder (My Db is Postgresql) along with gin. My code has become messy because of multiple nested if clauses. I'm using pagination and 3 sorting options (MostLiked, Oldest, Newest (default one). I wanna explicitly write raw SQL. What's a better way to write this code?
func GetAllPost(c *gin.Context) {
var queries map[string][]string = c.Request.URL.Query()
var posts []models.Post
// Setting up pagination
var page int
var limit int
var skip int
var noOfPosts float64
if queries["page"] != nil {
pageNo, err := strconv.Atoi(queries["page"][0])
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"error": "Invalid query param - page",
})
return
}
page = pageNo
} else {
page = 1
}
if queries["limit"] != nil {
limitInt, err := strconv.Atoi(queries["limit"][0])
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"error": "Invalid query param - limit",
})
return
}
limit = limitInt
} else {
limit = 6
}
skip = (page - 1) * limit
// Finding a single user's posts If needed
if queries["id"] != nil {
id, err := strconv.Atoi(queries["id"][0])
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"error": "Invalid query param - id",
})
return
}
if queries["sort"] != nil {
if slices.Contains(queries["sort"], "likesCount") {
// Sorting by Most liked
initializers.DB.Raw("SELECT * FROM posts WHERE created_by = ? ORDER BY ARRAY_LENGTH(liked_by, 1) DESC NULLS LAST OFFSET ? ROW FETCH NEXT ? ROWS ONLY", id, skip, limit).Find(&posts)
} else if slices.Contains(queries["sort"], "oldest") {
// Sorting by oldest post
initializers.DB.Raw("SELECT * FROM posts WHERE created_by = ? ORDER BY id ASC OFFSET ? ROW FETCH NEXT ? ROWS ONLY", id, skip, limit).Find(&posts)
} else {
// Sorting by latest post by default
initializers.DB.Raw("SELECT * FROM posts WHERE created_by = ? ORDER BY id DESC OFFSET ? ROW FETCH NEXT ? ROWS ONLY", id, skip, limit).Find(&posts)
}
} else {
// Forced to sort by default sorting again incase sort param is not provided
initializers.DB.Raw("SELECT * FROM posts ORDER BY id DESC OFFSET ? ROW FETCH NEXT ? ROWS ONLY", skip, limit).Find(&posts)
}
} else {
if queries["sort"] != nil {
if slices.Contains(queries["sort"], "likesCount") {
// Sorting by Most liked
initializers.DB.Raw("SELECT * FROM posts ORDER BY ARRAY_LENGTH(liked_by, 1) DESC NULLS LAST OFFSET ? ROW FETCH NEXT ? ROWS ONLY", skip, limit).Find(&posts)
} else if slices.Contains(queries["sort"], "oldest") {
// Sorting by oldest post
initializers.DB.Raw("SELECT * FROM posts ORDER BY id ASC OFFSET ? ROW FETCH NEXT ? ROWS ONLY", skip, limit).Find(&posts)
} else {
// Sorting by latest post by default
initializers.DB.Raw("SELECT * FROM posts ORDER BY id DESC OFFSET ? ROW FETCH NEXT ? ROWS ONLY", skip, limit).Find(&posts)
}
} else {
// Forced to sort by default sorting again incase sort param is not provided
initializers.DB.Raw("SELECT * FROM posts ORDER BY id DESC OFFSET ? ROW FETCH NEXT ? ROWS ONLY", skip, limit).Find(&posts)
}
}
// Getting no of total posts to calculate no of pages
initializers.DB.Raw("SELECT COUNT(id) FROM posts").Scan(&noOfPosts)
c.JSON(http.StatusOK, gin.H{
"posts": posts,
"noOfPages": math.Ceil(noOfPosts / 6),
})
}