在将数据发布到MongoDB时生成了额外的”id”字段。

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

Additional "id" field generated when posting into MongoDB

问题

我正在学习Go和Gin框架。
我构建了一个简单的微服务,连接到一个MongoDB集合,一切都正常,但是当我使用POST方法添加一个文档时,它添加了"id"字段而不是生成键"_id"字段,有没有办法避免这种情况?

这是我的函数:

func (r *Rest) CreatePost(c *gin.Context) {
    var postCollection = database.GetCollection(r.db, "GoDB")
    ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
    post := new(model.Post)
    defer cancel()

    if err := c.ShouldBindJSON(&post); err != nil {
        c.JSON(http.StatusBadRequest, gin.H{"message": err})
        log.Fatal(err)
        return
    }

    // 验证
    if err := post.Validate(); err == nil {
        c.JSON(http.StatusOK, gin.H{"input": "valid"})
    } else {
        c.JSON(http.StatusBadRequest, gin.H{"input validation": err.Error()})
        return
    }

    postPayload := model.Post{
        ID:      primitive.NewObjectID(),
        Title:   post.Title,
        Article: post.Article,
    }

    result, err := postCollection.InsertOne(ctx, postPayload)

    if err != nil {
        c.JSON(http.StatusInternalServerError, gin.H{"message": err})
        return
    }

    c.JSON(http.StatusOK, gin.H{"message": "Posted succesfully", "Data": 
        map[string]interface{}{"data": result}})
}

这是我的模型:

type Post struct {
    ID      primitive.ObjectID
    Title   string `validate:"required,gte=2,lte=20"`
    Article string `validate:"required,gte=4,lte=40"`
}

理解这个问题需要返回的Mongo文档如下图所示:

在将数据发布到MongoDB时生成了额外的”id”字段。

英文:

I'm learning Go and Gin framework.
I built a simple microservice connected to a MongoDB collection, everything works but when I add a document using a POST it adds the "id" field instead of generating the key "_id" field, is there a way to avoid this?

This is my func:

func (r *Rest) CreatePost(c *gin.Context) {
var postCollection = database.GetCollection(r.db, "GoDB")
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
post := new(model.Post)
defer cancel()

if err := c.ShouldBindJSON(&post); err != nil {
	c.JSON(http.StatusBadRequest, gin.H{"message": err})
	log.Fatal(err)
	return
}

// validation
if err := post.Validate(); err == nil {
	c.JSON(http.StatusOK, gin.H{"input": "valid"})
} else {
	c.JSON(http.StatusBadRequest, gin.H{"input validation": err.Error()})
	return
}

postPayload := model.Post{
	ID:      primitive.NewObjectID(),
	Title:   post.Title,
	Article: post.Article,
}

result, err := postCollection.InsertOne(ctx, postPayload)

if err != nil {
	c.JSON(http.StatusInternalServerError, gin.H{"message": err})
	return
}

c.JSON(http.StatusOK, gin.H{"message": "Posted succesfully", "Data": 
map[string]interface{}{"data": result}})
}

This is my model:

type Post struct {
ID      primitive.ObjectID
Title   string `validate:"required,gte=2,lte=20"`
Article string `validate:"required,gte=4,lte=40"`
}

在将数据发布到MongoDB时生成了额外的”id”字段。

答案1

得分: 0

默认情况下,ID 的键是 id。你应该使用 bson 标签来生成键 _id

type Post struct {
    ID      primitive.ObjectID `bson:"_id"`
    Title   string             `validate:"required,gte=2,lte=20"`
    Article string             `validate:"required,gte=4,lte=40"`
}

这里是文档

在编组结构时,每个字段都会转换为小写以生成相应 BSON 元素的键。例如,名为 "Foo" 的结构字段将生成键 "foo"。可以通过结构标签进行覆盖(例如,bson:"fooField" 生成键 "fooField")。

当文档中不包含名为 _id 的元素时,驱动程序会自动添加一个(参见源代码):

// ensureID inserts the given ObjectID as an element named "_id" at the
// beginning of the given BSON document if there is not an "_id" already. If
// there is already an element named "_id", the document is not modified. It
// returns the resulting document and the decoded Go value of the "_id" element.
func ensureID(
    doc bsoncore.Document,
    oid primitive.ObjectID,
    bsonOpts *options.BSONOptions,
    reg *bsoncodec.Registry,
) (bsoncore.Document, interface{}, error) {

这是一个示例:

package main

import (
    "context"

    "go.mongodb.org/mongo-driver/bson/primitive"
    "go.mongodb.org/mongo-driver/mongo"
    "go.mongodb.org/mongo-driver/mongo/options"
)

type Post struct {
    ID      primitive.ObjectID `bson:"_id"`
    Title   string             `validate:"required,gte=2,lte=20"`
    Article string             `validate:"required,gte=4,lte=40"`
}

func main() {
    client, err := mongo.Connect(context.Background(), options.Client().ApplyURI("mongodb://localhost"))
    if err != nil {
        panic(err)
    }

    postCollection := client.Database("demo").Collection("posts")
    post := Post{
        ID:      primitive.NewObjectID(),
        Title:   "test title",
        Article: "test content",
    }

    if _, err = postCollection.InsertOne(context.Background(), post); err != nil {
        panic(err)
    }
}

在数据库中创建的文档如下:

demo> db.posts.find()
[
  {
    _id: ObjectId("64a53bcbb7be31ae42e6c00c"),
    title: 'test title',
    article: 'test content'
  }
]
英文:

By default, the key for ID is id. You should use the bson tag to generate the key _id instead.

type Post struct {
	ID      primitive.ObjectID `bson:"_id"`
	Title   string             `validate:"required,gte=2,lte=20"`
	Article string             `validate:"required,gte=4,lte=40"`
}

Here is the doc:

> When marshalling a struct, each field will be lowercased to generate the key for the corresponding BSON element. For example, a struct field named "Foo" will generate key "foo". This can be overridden via a struct tag (e.g. bson:"fooField" to generate key "fooField" instead).

When the document does not contain an element named _id, the driver will add one automatically (see the source code):

// ensureID inserts the given ObjectID as an element named "_id" at the
// beginning of the given BSON document if there is not an "_id" already. If
// there is already an element named "_id", the document is not modified. It
// returns the resulting document and the decoded Go value of the "_id" element.
func ensureID(
	doc bsoncore.Document,
	oid primitive.ObjectID,
	bsonOpts *options.BSONOptions,
	reg *bsoncodec.Registry,
) (bsoncore.Document, interface{}, error) {

Here is a demo:

package main

import (
	"context"

	"go.mongodb.org/mongo-driver/bson/primitive"
	"go.mongodb.org/mongo-driver/mongo"
	"go.mongodb.org/mongo-driver/mongo/options"
)

type Post struct {
	ID      primitive.ObjectID `bson:"_id"`
	Title   string             `validate:"required,gte=2,lte=20"`
	Article string             `validate:"required,gte=4,lte=40"`
}

func main() {
	client, err := mongo.Connect(context.Background(), options.Client().ApplyURI("mongodb://localhost"))
	if err != nil {
		panic(err)
	}

	postCollection := client.Database("demo").Collection("posts")
	post := Post{
		ID:      primitive.NewObjectID(),
		Title:   "test title",
		Article: "test content",
	}
	if err != nil {
		panic(err)
	}

	if _, err = postCollection.InsertOne(context.Background(), post); err != nil {
		panic(err)
	}
}

And the document created in the database:

demo> db.posts.find()
[
  {
    _id: ObjectId("64a53bcbb7be31ae42e6c00c"),
    title: 'test title',
    article: 'test content'
  }
]

huangapple
  • 本文由 发表于 2023年7月5日 17:17:56
  • 转载请务必保留本文链接:https://go.coder-hub.com/76618854.html
匿名

发表评论

匿名网友

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

确定