I'm using Go and gqlgen to access my mongoDB database and was wondering how do I access the id
field from the database? This is what I have currently and _id
returns an empty string
type Post {
_id: ID!
title: String!
content: String!
comments: [Comment!]
author: User!
created: Date!
}
type Query {
post(_id: ID!): Post
...
}
func (r *queryResolver) Post(ctx context.Context, id string) (*model.Post, error) {
var post model.Post
_id, err := primitive.ObjectIDFromHex(id)
if err != nil {
return nil, err
}
err = db.Posts.FindOne(context.TODO(), bson.D{{Key: "_id", Value: _id}}).Decode(&post)
if err != nil {
return nil, err
}
return &post, nil
}
The ID type in gqlgen creates a string, but _id in mongo is probably a primitive.ObjectId which can create issues depending on how you interact with mongo.
Better to set a bson tag as _id
consider setting the following struct to overwrite the gql generated flow. You can convert the id into a string using the Hex() method.
type Post struct{
ID primitive.ObjectID `bson:"_id" json:"id"`
title: string
content: string
comments: []Comment
author: User
created: time.Time
}
You might want to do this automatically if you have many structs with _ids. To avoid having to overwrite, you can implement a hook to autogenerate the bson tags for you
type Post {
id: ID!
title: String!
content: String!
comments: [Comment!]
author: User!
created: Date!
}
now a new directory in your file structure called "hooks" and create a new file "bson.go"
copy and paste the following
package main
import (
"fmt"
"os"
"github.com/99designs/gqlgen/api"
"github.com/99designs/gqlgen/codegen/config"
"github.com/99designs/gqlgen/plugin/modelgen"
)
func mutateHook(b *modelgen.ModelBuild) *modelgen.ModelBuild {
for _, model := range b.Models {
for _, field := range model.Fields {
name := field.Name
if name == "id" {
name = "_id"
}
field.Tag += ` bson:"` + name + `"`
}
}
return b
}
func main() {
cfg, err := config.LoadConfigFromDefaultLocations()
if err != nil {
fmt.Fprintln(os.Stderr, "failed to load config", err.Error())
os.Exit(2)
}
p := modelgen.Plugin{
MutateHook: mutateHook,
}
err = api.Generate(cfg,
api.NoPlugins(),
api.AddPlugin(&p),
)
if err != nil {
fmt.Fprintln(os.Stderr, err.Error())
os.Exit(3)
}
}
now in your main.go add this to the top
//go:generate go run hooks/bson.go
now when you run go generate
not only will gqlgen do it's normal generation, but it will also add bson tags to all of our models. As well as any field with the name id to have a bson tag of _id
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.