I have recently started working with GO and tried to create an API. This was a basic API with few get
and post
endpoints. Every endpoint is working just fine but one. I am doing the same thing as in the other get endpoints but don't understand why am I getting the empty instance back from the mongoDB. And as far as I can guess, I think this is the problem due to data type.
This is my Post
struct.
package models
import (
"time"
"go.mongodb.org/mongo-driver/bson/primitive"
)
type Posts struct {
Id primitive.ObjectID `json:"id" bson:"_id" validate:"nil=false"`
Caption string `json:"caption" bson:"caption"`
ImageUrl string `json:"imageUrl" bson:"imageUrl" validate:"nil=false"`
Author string `json:"author" bson:"author" validate:"nil:false"`
Time time.Time `json:"time" bson:"time"`
}
This is the controller getPost
package controller
import (
"insta/models"
"log"
"net/http"
"github.com/gin-gonic/gin"
"go.mongodb.org/mongo-driver/bson"
// "go.mongodb.org/mongo-driver/bson/primitive"
)
func GetPost(c *gin.Context) {
var post models.Posts
postId := c.Param("postId")
client, ctx, cancel := getConnection()
defer cancel()
defer client.Disconnect(ctx)
err := client.Database("instagram").Collection("posts").FindOne(ctx, bson.M{"_id": postId}).Decode(&post)
if err != nil {
log.Printf("Couldn't get the Post")
}
c.JSON(http.StatusOK, gin.H{"post": post})
}
This is my main
package main
import (
"insta/controller"
"github.com/gin-gonic/gin"
)
func main() {
router := gin.Default()
router.GET("/posts/:postId" , controller.GetPost)
router.Run()
}
I am getting this response.
PostId
is valid
CodePudding user response:
The problem is the postId from the param is of type string
while the postId in mongodb is of type primitive.ObjectID
which are not the same.
The solution is to convert it to a MongoDB ObjectID
before querying.
func GetPost(c *gin.Context) {
var post models.Posts
postId := c.Param("postId")
postObjectId, err := primitive.ObjectIDFromHex(postId)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"message": "PostID is not a valid ObjectID"})
return
}
client, ctx, cancel := getConnection()
defer cancel()
defer client.Disconnect(ctx)
err = client.Database("instagram").Collection("posts").FindOne(ctx, bson.M{"_id": postObjectId}).Decode(&post)
// Check if document exists return 404 error
if errors.Is(err, mongo.ErrNoDocuments) {
c.JSON(http.StatusNotFound, gin.H{"message": "Post with the given id does not exist"})
return
}
// Mongodb network or server error
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"message": err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{"post": post})
}