在 Ubuntu 20.04 上使用 Golang 和 MongoDB 创建 CRUD 应用程序

介绍

MongoDB 是最好的基于文档的开源数据库管理系统之一。 由于其灵活的设计模式,您可以在广泛的业务系统中使用该应用程序,这是传统 SQL 数据库无法满足的。

凭借其强大的数据库架构,MongoDB 平台适用于设置管理产品数据、创建内容管理系统 (CMS) 以及在大多数情况下存储和查询大数据的系统。

另一方面,Golang 是一种快速、可扩展且易于学习的现代编程语言,用于编写高级软件应用程序。 由于 MongoDB 为 Golang 语言提供了一个全面的 API,您可以将这两个应用程序一起使用,为金融、电子商务、研究等提供解决方案。

在本指南中,您将使用 MongoDB 设置数据库并从自定义 Golang 应用程序与其通信,以在您的 Ubuntu 20.04 服务器上执行基本的创建、读取、更新和删除 (CRUD) 操作。

先决条件

要继续阅读本指南,请确保您已获得以下信息:

  • 一个 Ubuntu 20.04 服务器。
  • 非root用户 sudo 特权。
  • 使用用户帐户和密码配置的 MongoDB 数据库。
  • 一个 Golang 包。

1.创建一个MongoDB数据库

您的数据驱动应用程序必须能够存储、检索、更新和删除记录。 您只能在为您的软件设置数据库后执行所有这些操作。 SSH 到您的服务器并按照以下步骤初始化 MongoDB 数据库。

  1. 登录到您的 MongoDB 数据库。 代替 mongo_db_admin 与 admin 为您的数据库帐户。

    $ mongosh -u mongo_db_admin -p --authenticationDatabase admin
    
  2. Enter 出现提示时输入 MongoDB 帐户的密码,然后按 ENTER 继续。 接下来,运行下面的语句来创建一个 shop_db 数据库。

    test> use shop_db
    
  3. 确认您已切换到新版本 shop_db 数据库。

    switched to db shop_db
    
  4. 接下来,将三个文档插入一个新的 products 使用 MongoDB 收集 insertMany() 功能。

    shop_db> db.products.insertMany([
                {"product_id" : 1,
                 "product_name" : "LEATHER BELT",
                 "retail_price" : 24.35   
                },
                {"product_id" : 2,
                 "product_name" : "WINTER JACKET",
                 "retail_price" : 99.95    
                },
                {"product_id" : 3,
                 "product_name" : "WOOLEN SWEATER",
                 "retail_price" : 43.20
                }  
               ]);
    
  5. 通过确认下面的输出来确保命令成功。

    {
      acknowledged: true,
      insertedIds: {
        '0': ObjectId("62188b2358979df39bbcf178"),
        '1': ObjectId("62188b2358979df39bbcf179"),
        '2': ObjectId("62188b2358979df39bbcf17a")
      }
    }
    
  6. 接下来,使用以下语句查询 products 收集以确保数据到位。

    shop_db> db.products.find()
    
  7. 您应该获得所有产品的列表以及相关的 _ids 如下。

    [
      {
        _id: ObjectId("62188b2358979df39bbcf178"),
        product_id: 1,
        product_name: 'LEATHER BELT',
        retail_price: 24.35
      },
      {
        _id: ObjectId("62188b2358979df39bbcf179"),
        product_id: 2,
        product_name: 'WINTER JACKET',
        retail_price: 99.95
      },
      {
        _id: ObjectId("62188b2358979df39bbcf17a"),
        product_id: 3,
        product_name: 'WOOLEN SWEATER',
        retail_price: 43.2
      }
    ]
    
  8. 从 MongoDB 服务器注销。

    shop_db> quit
    
  9. 您现在已经设置了 shop_db 数据库, products 收藏和样本 文件. 在接下来的步骤中,您将使用 Golang 语言创建一些脚本来操作您的 MongoDB 集合。

2. 创建一个 main.go 文件

main.go 文件将保存 main() 为您的应用程序提供功能。 这是执行应用程序时触发的主要方法。

  1. 在创建源代码之前 main.go 文件,创建一个 project 目录将您的源代码与其余的 Linux 文件分开。

    $ mkdir project
    
  2. 然后切换到新的 project 目录。

    $ cd project
    
  3. 接下来,使用 nano 文本编辑器打开一个新的 main.go 用于编辑目的的文件。

    $ nano main.go
    
  4. 随着 main.go 打开文件,在文件中输入以下信息。 代替 mongo_db_adminEXAMPLE_PASSWORD 为您的 MongoDB 用户帐户设置正确的值。

    package main
    
    import (
        "context"
        "net/http"
        "encoding/json" 
        _"log" 
        "fmt" 
        "go.mongodb.org/mongo-driver/mongo" 
    "go.mongodb.org/mongo-driver/mongo/options"         
    )
    
    const (  
        dbUser = "mongo_db_admin"
        dbPass = "EXAMPLE_PASSWORD"
        dbName = "shop_db"
    )
    
    func main() {
         http.HandleFunc("/api/v1/products", requestHandler)
         http.ListenAndServe(":8080", nil)
    }
    
    func requestHandler(w http.ResponseWriter, req *http.Request) {
    
        w.Header().Set("Content-Type", "application/json")
    
        response := map[string]interface{}{}
    
        ctx := context.Background()
    
        client, err := mongo.Connect(ctx, options.Client().ApplyURI("mongodb://" + dbUser + ":" + dbPass + "@localhost:27017"))
    
        if err != nil { 
            fmt.Println(err.Error())
        } 
    
        collection := client.Database(dbName).Collection("products")  
    
        data := map[string]interface{}{} 
    
        err = json.NewDecoder(req.Body).Decode(&data)
    
        if err != nil { 
            fmt.Println(err.Error())
        }
    
        switch req.Method {
            case "POST":
                response, err = createRecord(collection, ctx, data)
            case "GET":
                response, err = getRecords(collection, ctx)
            case "PUT":
                response, err = updateRecord(collection, ctx, data)
            case "DELETE":
                response, err = deleteRecord(collection, ctx, data)
        }
    
        if err != nil { 
            response = map[string]interface{}{"error": err.Error(),}  
        } 
    
        enc := json.NewEncoder(w)
        enc.SetIndent("", "  ")
    
        if err := enc.Encode(response); err != nil {
            fmt.Println(err.Error())
        }   
    }
    
  5. Save 和 close 完成编辑后的文件。

  6. 在上面的文件中,您正在创建一个 Web 服务器,用于侦听端口上的传入 HTTP 请求 8080 使用语句 http.HandleFunc("/api/v1/products", requestHandler)http.ListenAndServe(":8080", nil).

  7. 在下面 requestHandler() 函数,您正在连接到您之前创建的 MongoDB 实例。 接下来,您正在使用 Golang switch 通过传递一个语句将 HTTP 请求路由到相应的 CRUD 函数 products 收藏参考。 最后,您将使用 JSON 函数以人类可读的格式格式化和输出数据。

  8. 现在您已经创建了 main.go 文件,您现在将在不同的文件上设置单独的函数来处理您的应用程序的所有 CRUD 操作。

3.设置一个新的 create_record.go 文件

您要为 CRUD 操作设置的第一个文件是 create_record.go 文件。 该文件包含一个用于将文档插入到 products 收藏。

  1. 运行下面的命令来设置 create_record.go 文件。

    $ nano create_record.go
    
  2. 接下来,在文件中输入以下信息。

    package main
    
    import (
        "context"      
        "go.mongodb.org/mongo-driver/mongo"       
    )
    
    func createRecord(collection *mongo.Collection, ctx context.Context, data map[string]interface{})(map[string]interface{}, error){     
    
        req, err := collection.InsertOne(ctx, data)
    
        if err != nil { 
            return nil, err                    
        }
    
        insertedId := req.InsertedID
    
        res := map[string]interface{}{
                   "data" : map[string]interface{}{                            
                        "insertedId": insertedId,
                    },
               } 
    
        return res, nil
    }
    
  3. Save 和 close 文件。

  4. 上述文件中的主要功能是 collection.InsertOne(ctx, data) 它将来自请求 HTTP 客户端的 BSON 有效负载保存到 MongoDB 数据库。 在上述文件下,您将返回 insertedId 如果语句执行没有任何错误,则为新文档。

  5. 接下来,您将设置一个函数以从 MongoDB 集合中删除文档。

4. 创建一个 delete_record.go 文件

与任何其他应用程序一样,您必须提供从 products 如果您不再需要它们,请收藏。

  1. 打开一个新的 delete_record.go 文件使用 nano.

    $ nano delete_record.go
    
  2. 接下来,将以下信息输入到 delete_record.go 文件。

    package main
    
    import (
        "context"          
        "go.mongodb.org/mongo-driver/mongo"     
        "go.mongodb.org/mongo-driver/bson"
    )
    
    func deleteRecord(collection *mongo.Collection, ctx context.Context, data map[string]interface{})(map[string]interface{}, error){
    
        _, err := collection.DeleteOne(ctx, bson.M{"product_id": data["product_id"]})
    
        if err != nil { 
            return nil, err                    
        }     
    
        res := map[string]interface{}{
                   "data" : "Document deleted successfully.",   
               } 
    
        return res, nil
    }
    
  3. Save 和 close 文件。

  4. 在上面的文件中,您正在使用该功能 collection.DeleteOne(...) 从 MongoDB 数据库中删除文档。 为确保删除正确的文档,您正在检索 product_id 您要使用语句删除的项目的 bson.M{"product_id": data["product_id"]}. 换句话说,你应该通过 product_id 提交时在 HTTP 有效负载中 DELETE 向应用程序请求。

  5. 接下来,您将设置一个函数来更新文档。

5.创建一个新的 update_record.go 文件

您将使用 update_record.go 文件以更改您的文档。 功能(updateRecord()) 在此文件下依赖于包含要更新的字段以及唯一的有效负载 product_id 的文件。

  1. 采用 nano 开辟一个新的 update_record.go 文件。

    $ nano update_record.go
    
  2. 接下来,将以下信息输入到 update_record.go 文件。

    package main
    
    import (
        "context"
        "go.mongodb.org/mongo-driver/bson"     
        "go.mongodb.org/mongo-driver/mongo" 
    )
    
    func updateRecord(collection *mongo.Collection, ctx context.Context, data map[string]interface{})(map[string]interface{}, error){            
    
        filter := bson.M{"product_id": data["product_id"]}
        fields := bson.M{"$set": data}
    
        _, err := collection.UpdateOne(ctx, filter, fields)
    
        if err != nil { 
            return nil, err                    
        }
    
        res := map[string]interface{}{
                   "data" : "Document updated successfully.",   
               } 
    
        return res, nil
    }
    
  3. 在上面的文件中,您首先提供了一个 filter 要使用语句更新的文档的参数 filter := bson.M{"product_id": data["product_id"]}. 然后,您使用语句提交新的文档值 fields := bson.M{"$set": data}. 这 data 这里的值来自请求客户端提交的 HTTP 有效负载。

  4. 接下来,您正在使用该功能 collection.UpdateOne(ctx, filter, fields) 向您的收藏提交更新请求。 在下一步中,您将创建一个用于从 MongoDB 集合中检索记录的函数。

6.创建一个新的 get_records.go 文件

Golang 的 MongoDB API 带有非常直观的函数,用于以地图的形式从数据库中检索文档。 您将使用这些函数来查询您的数据库集合并将文档返回到 main.go 您之前创建的文件。

  1. 采用 nano 创建一个新的 get_records.go 文件。

    $ nano get_records.go
    
  2. 然后,将以下信息输入到 get_records.go 文件。

    package main
    
    import (
        "context"          
        "go.mongodb.org/mongo-driver/bson"
        "go.mongodb.org/mongo-driver/mongo" 
    )
    
    func getRecords(collection *mongo.Collection, ctx context.Context)(map[string]interface{}, error){ 
    
        cur, err := collection.Find(ctx, bson.D{})
    
        if err != nil { 
            return nil, err
        }
    
        defer cur.Close(ctx) 
    
        var products []bson.M           
    
        for cur.Next(ctx) {
    
            var product bson.M
    
            if err = cur.Decode(&product); err != nil {
                return nil, err
            }
    
            products = append(products, product)
    
        }
    
        res := map[string]interface{}{}
    
        res = map[string]interface{}{
                  "data" : products,   
              }             
    
        return res, nil
    }
    
  3. Save 和 close 文件。

  4. 在上面的文件中,您正在使用该函数 cur, err := collection.Find(ctx, bson.D{}) 返回已保存在您的文档中的光标 products 收藏。 然后,您正在使用 for cur.Next(ctx) {...} 循环遍历您稍后附加到的文档 products []bson.M 大批。

  5. 最后,您将数据作为映射返回给调用函数 [string]interface{}. 您现在已经为您的应用程序设置了所有 CRUD 函数。 在下一步中,您将测试应用程序以确保一切都按预期工作。

7. 测试 Golang 应用程序

在此步骤中,您将测试应用程序以确保它可以处理所有 CRUD 操作而不会出现任何错误。

  1. 为您的 Golang 应用程序导入 MongoDB 驱动程序。

    $ go get go.mongodb.org/mongo-driver/mongo
    
  2. 接下来,执行以下命令来运行您的应用程序。 下面的命令允许您的应用程序启动 Web 服务器并侦听端口上的传入 HTTP 连接 8080 并具有拦截功能。 不要在这个 SSH 终端窗口上运行任何其他命令。

    $ go run ./
    
  3. 接下来,在单独的终端窗口中与您的服务器建立一个新的 SSH 会话。

  4. 尝试通过运行 curl 下面的命令。

    $ curl -X POST localhost:8080/api/v1/products -H "Content-Type: application/json" -d '{"product_id": 4, "product_name": "WIRELESS KEYBOARD",  "retail_price": 45.30}'
    
  5. 你应该得到一个 insertedId 的新记录,如下图所示。

    {
      "data": {
        "insertedId": "621c9acf3f4e8882c3eeabef"
      }
    }
    
  6. 接下来,使用以下命令从 products 收藏。

    $ curl -X GET localhost:8080/api/v1/products
    
  7. 您现在应该看到四个文档的列表。 前三个是你第一次初始化数据库时设置的文档,最后一个记录(WIRELESS KEYBOARD) 是您刚刚使用 curl 命令。

    {
      "data": [
        {
          "_id": "621c9aaf35ece941bcc5b80d",
          "product_id": 1,
          "product_name": "LEATHER BELT",
          "retail_price": 24.35
        },
        {
          "_id": "621c9aaf35ece941bcc5b80e",
          "product_id": 2,
          "product_name": "WINTER JACKET",
          "retail_price": 99.95
        },
        {
          "_id": "621c9aaf35ece941bcc5b80f",
          "product_id": 3,
          "product_name": "WOOLEN SWEATER",
          "retail_price": 43.2
        },
        {
          "_id": "621c9acf3f4e8882c3eeabef",
          "product_id": 4,
          "product_name": "WIRELESS KEYBOARD",
          "retail_price": 45.3
        }
      ]
    }
    
  8. 接下来,运行以下命令以使用 product_id1 并改变它 product_nameLEATHER BELTMETAL BUCKLE LEATHER BELT.

    $ curl -X PUT localhost:8080/api/v1/products -H "Content-Type: application/json" -d '{"product_id": 1, "product_name": "METAL BUCKLE LEATHER BELT",  "retail_price": 45.30}'
    
  9. 以下输出确认您已成功更新产品详细信息。

    {
      "data": "Document updated successfully."
    }
    
  10. 删除文档 product_id4(WIRELESS KEYBOARD) 通过运行以下命令。

    $ curl -X DELETE localhost:8080/api/v1/products -H "Content-Type: application/json" -d '{"product_id": 4}'
    
  11. 您应该收到以下确认消息。

    {
      "data": "Document deleted successfully."
    }
    
  12. 接下来,再次检索记录以确保您已经完成了 UPDATEDELETE 中的操作 products 收藏。

    $ curl -X GET localhost:8080/api/v1/products
    
  13. 正如您从下面的输出中看到的那样,您已经删除了带有 product_id4,并且您还成功地更新了文档的值 product_id1METAL BUCKLE LEATHER BELT.

    {
      "data": [
        {
          "_id": "621c9aaf35ece941bcc5b80d",
          "product_id": 1,
          "product_name": "METAL BUCKLE LEATHER BELT",
          "retail_price": 45.3
        },
        {
          "_id": "621c9aaf35ece941bcc5b80e",
          "product_id": 2,
          "product_name": "WINTER JACKET",
          "retail_price": 99.95
        },
        {
          "_id": "621c9aaf35ece941bcc5b80f",
          "product_id": 3,
          "product_name": "WOOLEN SWEATER",
          "retail_price": 43.2
        }
      ]        
    }
    
  14. 您的代码现在按预期工作,并且能够处理所有 CRUD 操作。

结论

在本指南中,您已使用 Golang 编程语言在 Ubuntu 20.04 服务器上连接和操作 MongoDB 集合中的数据。 在使用 Golang 设计下一个数据驱动的 MongoDB 应用程序时,请使用本指南中的函数。

注:本教程在Vultr VPS上测试通过,如需部署请前往Vultr.com