CRUD with Postgres and MongoDB?

WBOY
Release: 2024-02-09 14:00:10
forward
731 people have browsed it

使用 Postgres 和 MongoDB 进行 CRUD?

php Editor Xigua will take you through this article to learn how to use Postgres and MongoDB for CRUD operations. Postgres is a relational database, while MongoDB is a document database. CRUD operations refer to the process of creating (Create), reading (Read), updating (Update) and deleting (Delete) data. By combining these two different types of databases, you can choose the most suitable database for data operations based on different needs to improve efficiency and flexibility. Next, let us explore the application of these two databases in CRUD operations!

Question content

I am fairly new to Go and backends, and am participating in the Go internship program. We built a CRUD that connects to a psql database and now I'm told to connect to mongoDB, which we will use for development and PSQL will be used for production. Do I have to create a new handler for mongo from scratch or can I use the same handler and somehow determine the type of database being used and use the logic accordingly? For example, I have a handler for the user registration endpoint:

func (ctrl *UserController) Register(c *gin.Context) {
    var user models.User
    if err := c.BindJSON(&user); err != nil {
        c.AbortWithStatusJSON(http.StatusUnprocessableEntity, gin.H{
            "error":   true,
            "message": err.Error(),
        })
        return
    }
    err := ctrl.userService.Register(&user)
    if err != nil {
        c.AbortWithStatusJSON(http.StatusUnprocessableEntity, gin.H{
            "error":   true,
            "message": err.Error(),
        })
        return
    }

    c.JSON(http.StatusCreated, gin.H{
        "message": "successfully created an user",
    })
}

func (svc *UserService) Register(user *models.User) error {
    if svc.userRepo.CheckIfEmailExists(user.Email) {
        return errors.New("user already registered")
    }
    hash, err := svc.generatePasswordHash(user.Password)
    if err != nil {
        return errors.New("err can't register user")
    }

    user.Password = hash

    return svc.userRepo.Insert(user)
}

func (repo *UserRepository) CheckIfEmailExists(mail string) bool {
    var user models.User
    err := repo.dbClient.Debug().Model(models.User{}).Where("email = ?", mail).Find(&user).Error
    return errors.Is(err, gorm.ErrRecordNotFound)
}

func (repo *UserRepository) Insert(user *models.User) error {
    err := repo.dbClient.Debug().Model(models.User{}).Create(user).Error
    if err != nil {
        log.Printf("failed to insert user: %v\n", err)
        return err
    }
    return nil
}
Copy after login

I built the insert, register and CheckIfEmailExists functions for mongo:

func (repo *UserRepository) InsertInMongo(user *models.UserB) error {
    coll := repo.mongoClient.DB.Collection("users")
    _, err := coll.InsertOne(context.TODO(), user)
    if err != nil {
        log.Printf("failed to insert user: %v\n", err)
        return err
    }
    return nil
}

func (svc *UserService) RegisterToMongo(user *models.UserB) error {
    check := svc.userRepo.CheckIfEmailExistsInMongo(user.Email)
    if check {
        return errors.New("user already registered")
    }
    hash, err := svc.generatePasswordHash(user.Password)
    if err != nil {
        return errors.New("err can't register user")
    }
    user.Password = hash
    return svc.userRepo.InsertInMongo(user)
}

func (repo *UserRepository) CheckIfEmailExistsInMongo(email string) bool {
    coll := repo.mongoClient.Collection
    filter := bson.D{{Key: "email", Value: email}}

    count, err := coll.CountDocuments(context.TODO(), filter)
    if err != nil {
        panic(err)
    }
    if count != 0 {
        return true
    }
    return false
}
Copy after login

Solution

You did not provide code on how to create UserService.

Ideally, you should have an interface that looks like this:

type UserRepository interface {
    CheckIfEmailExists(mail string) bool
    Insert(user *models.User) error
    …
}
Copy after login

Then, the UserService should be created like this:

// We use the interface as param
func NewUserService(userRepo UserRepository) UserService {
    return UserService{
        UserRepo: userRepo
    }
}
Copy after login

And you will have two separate repositories, both implementing the UserRepository interface - this means they should have methods with the same name and same signature (parameters, return type) as the interface:

mongo_user_repository.go

Type MongoUserRepo struct {
    …
}

func (repo MongoUserRepo) CheckIfEmailExists(mail string) bool {
  … some mongo logic here
}

func (repo MongoUserRepo) Insert(user *models.User) error {
  … some mongo logic here
}
Copy after login

postgres_user_repository.go

type PostgresUserRepo struct {
    …
}

func (repo PostgresUserRepo) CheckIfEmailExists(mail string) bool {
  … some postgres logic here
}

func (repo PostgresUserRepo) Insert(user *models.User) error {
  … some postgres logic here
}
Copy after login

You can pass any of these depending on the use case, as in the (very bad) example below:

main.go

…

var userService UserService

if os.Getenv(“environment”) == “prod” {
    userService = NewUserService(postgreUserRepo)
} else if os.Getenv(“environment”) == “dev” {
    userService = NewUserService(mongoUserRepo)
}
Copy after login

The above is the detailed content of CRUD with Postgres and MongoDB?. For more information, please follow other related articles on the PHP Chinese website!

Related labels:
source:stackoverflow.com
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
About us Disclaimer Sitemap
php.cn:Public welfare online PHP training,Help PHP learners grow quickly!