Looking for a better way to handle a controller function with multiple sorting using gorm (go & gin)

475 Views Asked by At

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),
})
}
0

There are 0 best solutions below