I'm using fiber and mongodb. Field "field" is needed to obtain certain data to unload the load on the database. If field "field" is empty, then needs to output all the data from the database to make work easier to frontend. I don't like this crutch. Is there a much better solution?
func GetUserById(c *fiber.Ctx) error {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
var userId = c.Params("userId")
defer cancel()
objId, _ := primitive.ObjectIDFromHex(userId)
// Creates options for search.
opts, err := search.GetOneOptions(c, models.UserModel{})
if err != nil {
return responses.Response(c, http.StatusBadRequest, err.Error())
}
if c.Query("field") != "" {
var user models.UserModelOmitempty
err = usersCollection.FindOne(ctx, bson.M{"_id": objId}, opts).Decode(&user)
if err != nil {
return responses.Response(c, http.StatusBadRequest, "user not found")
}
return responses.ResponseWithData(c, http.StatusOK, "success", user)
} else {
var user models.UserModel
err = usersCollection.FindOne(ctx, bson.M{"_id": objId}, opts).Decode(&user)
if err != nil {
return responses.Response(c, http.StatusBadRequest, "user not found")
}
return responses.ResponseWithData(c, http.StatusOK, "success", user)
}
}
models.UserModel
type UserModel struct {
Id primitive.ObjectID `json:"id" bson:"_id" query:"string"`
Name string `json:"name" bson:"name" validate:"required" query:"string"`
Email string `json:"email" bson:"email" validate:"required" query:"string"`
Password string `json:"-" bson:"password" validate:"required"`
CreatedAt int64 `json:"createdAt" bson:"createdAt" query:"int"`
Rights string `json:"rights" bson:"rights" query:"string"`
PhotoUrl string `json:"photoUrl" bson:"photoUrl"`
Sex string `json:"sex" bson:"sex" query:"string"`
BirthDate int64 `json:"birthDate" bson:"birthDate" query:"int"`
Country string `json:"country" bson:"country" query:"string"`
EmailSubscribe bool `json:"emailSubscribe" bson:"emailSubscribe" query:"bool"`
AccountConfirmed bool `json:"accountConfirmed" bson:"accountConfirmed" query:"bool"`
}
models.UserModelOmitempty
type UserModelOmitempty struct {
Id primitive.ObjectID `json:"id" bson:"_id" query:"string"`
Name string `json:"name,omitempty" bson:"name" validate:"required" query:"string"`
Email string `json:"email,omitempty" bson:"email" validate:"required" query:"string"`
Password string `json:"-" bson:"password" validate:"required"`
CreatedAt int64 `json:"createdAt,omitempty" bson:"createdAt" query:"int"`
Rights string `json:"rights,omitempty" bson:"rights" query:"string"`
PhotoUrl string `json:"photoUrl,omitempty" bson:"photoUrl"`
Sex string `json:"sex,omitempty" bson:"sex" query:"string"`
BirthDate int64 `json:"birthDate,omitempty" bson:"birthDate" query:"int"`
Country string `json:"country,omitempty" bson:"country" query:"string"`
EmailSubscribe bool `json:"emailSubscribe,omitempty" bson:"emailSubscribe" query:"bool"`
AccountConfirmed bool `json:"accountConfirmed,omitempty" bson:"accountConfirmed" query:"bool"`
}
Result in postman: without field
-
\$\begingroup\$ I'm assuming this snippet is part of a function or method. Where is the rest of it? I see code duplication so we can probably improve it, but a good review requires more context. \$\endgroup\$Mast– Mast2022年06月26日 09:00:45 +00:00Commented Jun 26, 2022 at 9:00
2 Answers 2
Since the types seem to be identical except for the JSON tags, you could use either models.UserModel or models.UserModelOmitempty for most of code, until the point where serialization comes into play, which will be when you call responses.Response(...) and then convert to the correct type:
var user
err = usersCollection.FindOne(ctx, bson.M{"_id": objId}, opts).Decode(&user)
if err != nil {
return responses.Response(c, http.StatusBadRequest, "user not found")
}
if c.Query("field") != "" {
// No field specified, so omitting empty fields
return responses.ResponseWithData(c, http.StatusOK, "success", models.UserModelOmitempty(user))
}
return responses.ResponseWithData(c, http.StatusOK, "success", user)
Thanks @muru for giving me the idea. The result here:
Models.
type UserModel struct {
Id primitive.ObjectID `json:"id" bson:"_id" query:"string"`
Name string `json:"name" bson:"name" validate:"required" query:"string"`
Email string `json:"email" bson:"email" validate:"required" query:"string"`
Password string `json:"-" bson:"password" validate:"required"`
CreatedAt *time.Time `json:"createdAt" bson:"createdAt" query:"date"`
Rights string `json:"rights" bson:"rights" query:"string"`
PhotoUrl string `json:"photoUrl" bson:"photoUrl"`
Sex string `json:"sex" bson:"sex" query:"string"`
BirthDate *time.Time `json:"birthDate" bson:"birthDate" query:"date"`
Country string `json:"country" bson:"country" query:"string"`
EmailSubscribe bool `json:"emailSubscribe" bson:"emailSubscribe" query:"bool"`
AccountConfirmed bool `json:"accountConfirmed" bson:"accountConfirmed" query:"bool"`
}
type UserModelOmitempty struct {
Id primitive.ObjectID `json:"id" bson:"_id"`
Name string `json:"name,omitempty"`
Email string `json:"email,omitempty"`
Password string `json:"-" bson:"password"`
CreatedAt *time.Time `json:"createdAt,omitempty"`
Rights string `json:"rights,omitempty"`
PhotoUrl string `json:"photoUrl,omitempty"`
Sex string `json:"sex,omitempty"`
BirthDate *time.Time `json:"birthDate,omitempty"`
Country string `json:"country,omitempty"`
EmailSubscribe bool `json:"emailSubscribe,omitempty"`
AccountConfirmed bool `json:"accountConfirmed,omitempty"`
}
func (u *UserModel) ConvertToOmitempty() interface{} {
return UserModelOmitempty{
Id: u.Id,
Name: u.Name,
Email: u.Email,
CreatedAt: u.CreatedAt,
Rights: u.Rights,
PhotoUrl: u.PhotoUrl,
Sex: u.Sex,
BirthDate: u.BirthDate,
Country: u.Country,
EmailSubscribe: u.EmailSubscribe,
AccountConfirmed: u.AccountConfirmed,
}
}
Controller.
func GetUserById(c *fiber.Ctx) error {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
var userId = c.Params("userId")
var user models.UserModel
defer cancel()
objId, _ := primitive.ObjectIDFromHex(userId)
// Creates options for search.
opts, err := search.GetOneOptions(c, models.UserModel{})
if err != nil {
return responses.Response(c, http.StatusBadRequest, err.Error())
}
err = usersCollection.FindOne(ctx, bson.M{"_id": objId}, opts).Decode(&user)
if err != nil {
return responses.Response(c, http.StatusBadRequest, "user not found")
}
if c.Query("field") != "" {
return responses.ResponseWithData(c, http.StatusOK, "success", user.ConvertToOmitempty())
}
return responses.ResponseWithData(c, http.StatusOK, "success", user)
}
```
-
2\$\begingroup\$ Rather than post updated code as an answer, you should post a follow up question with a link back to this question. You should also read What to do when someone answers my question. \$\endgroup\$2022年06月26日 13:49:34 +00:00Commented Jun 26, 2022 at 13:49