每次发出GET请求时都会得到”_id: 000000000″。

huangapple go评论87阅读模式
英文:

Getting "_id : 000000000" for every get request

问题

我最近开始使用GO并尝试创建一个API。这是一个基本的API,有几个getpost端点。每个端点都正常工作,但有一个例外。我在做与其他get端点相同的事情,但不明白为什么从mongoDB中返回一个空实例。据我猜测,我认为这是由于数据类型的问题。以下是我的Post结构体。

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"`
}

这是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})
}

这是我的main函数。

package main

import (
	"insta/controller"

	"github.com/gin-gonic/gin"
)

func main() {
	router := gin.Default()
	router.GET("/posts/:postId", controller.GetPost)
	router.Run()
}

我得到了这个响应。

每次发出GET请求时都会得到”_id: 000000000″。

PostId是有效的。

每次发出GET请求时都会得到”_id: 000000000″。

英文:

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.<br><br> This is my Post struct.

package models

import (
	&quot;time&quot;

	&quot;go.mongodb.org/mongo-driver/bson/primitive&quot;
)

type Posts struct {
	Id       primitive.ObjectID `json:&quot;id&quot; bson:&quot;_id&quot; validate:&quot;nil=false&quot;`
	Caption  string             `json:&quot;caption&quot; bson:&quot;caption&quot;`
	ImageUrl string             `json:&quot;imageUrl&quot; bson:&quot;imageUrl&quot; validate:&quot;nil=false&quot;`
	Author   string             `json:&quot;author&quot; bson:&quot;author&quot; validate:&quot;nil:false&quot;`
	Time     time.Time          `json:&quot;time&quot; bson:&quot;time&quot;`
}

This is the controller getPost

package controller

import (
	&quot;insta/models&quot;
	&quot;log&quot;
	&quot;net/http&quot;

	&quot;github.com/gin-gonic/gin&quot;
	&quot;go.mongodb.org/mongo-driver/bson&quot;
	// &quot;go.mongodb.org/mongo-driver/bson/primitive&quot;
)

func GetPost(c *gin.Context) {
	var post models.Posts
	postId := c.Param(&quot;postId&quot;)
	client, ctx, cancel := getConnection()
	defer cancel()
	defer client.Disconnect(ctx)
	err := client.Database(&quot;instagram&quot;).Collection(&quot;posts&quot;).FindOne(ctx, bson.M{&quot;_id&quot;: postId}).Decode(&amp;post)
	if err != nil {
		log.Printf(&quot;Couldn&#39;t get the Post&quot;)
	}
	c.JSON(http.StatusOK, gin.H{&quot;post&quot;: post})
}

This is my main

package main

import (
	&quot;insta/controller&quot;

	&quot;github.com/gin-gonic/gin&quot;
)

func main() {
	router := gin.Default()
	router.GET(&quot;/posts/:postId&quot; , controller.GetPost)
	router.Run()
}

I am getting this response.

每次发出GET请求时都会得到”_id: 000000000″。

PostId is valid

每次发出GET请求时都会得到”_id: 000000000″。

答案1

得分: 1

问题是参数中的postId是string类型,而mongodb中的postId是primitive.ObjectID类型,它们不相同。

解决方案是在查询之前将其转换为MongoDB的ObjectID类型。

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)
	// 检查文档是否存在,如果不存在返回404错误
	if errors.Is(err, mongo.ErrNoDocuments) {
		c.JSON(http.StatusNotFound, gin.H{"message": "Post with the given id does not exist"})
		return
	}

	// Mongodb网络或服务器错误
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"message": err.Error()})
		return
	}

	c.JSON(http.StatusOK, gin.H{"post": post})
}
英文:

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(&quot;postId&quot;)
	postObjectId, err := primitive.ObjectIDFromHex(postId)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{&quot;message&quot;: &quot;PostID is not a valid ObjectID&quot;})
		return
	}

	client, ctx, cancel := getConnection()
	defer cancel()
	defer client.Disconnect(ctx)

	err = client.Database(&quot;instagram&quot;).Collection(&quot;posts&quot;).FindOne(ctx, bson.M{&quot;_id&quot;: postObjectId}).Decode(&amp;post)
	// Check if document exists return 404 error
	if errors.Is(err, mongo.ErrNoDocuments) {
		c.JSON(http.StatusNotFound, gin.H{&quot;message&quot;: &quot;Post with the given id does not exist&quot;})
		return
	}

	// Mongodb network or server error
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{&quot;message&quot;: err.Error()})
		return
	}

	c.JSON(http.StatusOK, gin.H{&quot;post&quot;: post})
}

huangapple
  • 本文由 发表于 2021年10月10日 17:39:01
  • 转载请务必保留本文链接:https://go.coder-hub.com/69514024.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定