在 CentOS 上安装 MongoDB

一、安装 MongoDB 社区版

使用 yum 包管理器安装 MongoDB。

  1. 为 MongoDB 创建 /etc/yum.repos.d/mongodb-org-4.4.repo 文件。
    # nano /etc/yum.repos.d/mongodb-org-4.4.repo
  2. 将以下内容粘贴到编辑器中:
    [mongodb-org-4.4]
    
    name=MongoDB Repository
    
    baseurl=https://repo.mongodb.org/yum/redhat/$releasever/mongodb-org/4.4/x86_64/
    
    gpgcheck=1
    
    enabled=1
    
    gpgkey=https://www.mongodb.org/static/pgp/server-4.4.asc
  3. 保存并退出文件。
  4. 要安装 MongoDB 的最新稳定版本,请执行以下操作:
    # sudo yum install -y mongodb-org

如果您需要安装特定版本或阻止自动升级。

二、设置 MongoDB

  1. 启动MongoDB。
    # systemctl start mongod.service
    
    # systemctl enable mongod.service
  2. 连接到MongoDB。
    # mongo

 三、后续步骤

默认情况下,MongoDB 并不安全。使用我们的指南来配置 MongoDB 安全性和身份验证。

注意:可以安全地忽略与 相关的任何启动警告。要防止出现这些警告,请通过运行 来验证扇区是否“如警告中所述”。如果输出大于 512,请运行以下命令:Readaheadblockdev –getra /dev/vda1

blockdev --setra 512 /dev/vda1

systemctl restart mongod

现在将解决该警告。

将 MongoDB 与 Node.js 一起使用

一、介绍

MongoDB 是一个 NoSQL数据库,将数据存储在由字段值对组成的文档中。这些是使用 BSON(JSON 的二进制表示形式)存储的。MongoDB 文档类似于关系数据库表中的行,文档字段(键值对)类似于列。MongoDB 文档是集合的一部分,一个或多个集合数据库的一部分。MongoDB API支持常规 CRUD 操作(创建,读取,更新,删除)以及聚合,地理空间查询和文本搜索功能。MongoDB 还提供高可用性和复制。您可以在多个MongoDB 服务器(称为副本集)之间分发数据,以提供冗余和分片。

本文将通过一个完整的示例引导您了解如何在 Docker 中设置 MongoDB 副本集、部署客户端应用程序以及探索更改流。它将涵盖以下内容:

  • MongoDB 和更改流的概述。
  • 如何使用 MongoDB Go 驱动程序。
  • 应用程序设置和部署
  • 测试应用程序并了解如何使用恢复令牌。

MongoDB 为许多客户端驱动程序提供官方支持,包括 Java,Python,Node.js,PHP,Ruby,Swift,C,C++,C# 和 Go。在本文中,您将使用 MongoDB 的 Go 驱动程序来构建更改流处理器和 REST API 应用程序。

1.1、MongoDB 更改流

使用更改流,您可以实时访问MongoDB数据更新。应用程序不需要担心处理 oplog 和更改流的低级操作细节。可以订阅集合、数据库或整个部署上的所有数据更改。由于更改流使用聚合框架,因此应用程序还可以筛选特定更改或转换通知。可以将更改流用于副本集(这是本文将使用的内容)和分片设置。

更改流仅在更新操作期间返回字段的差异(这是默认行为)。但您可以将其配置为返回更新文档的最新提交版本。还可以提供一个或多个管道阶段的数组来控制更改流输出。例如 -、、 等。$addFields$match$project

1.2、恢复令牌

恢复令牌允许应用程序保存进度并防止潜在的数据丢失。如果更改流应用程序崩溃,它将无法在此期间检测到数据库更改。恢复令牌可用于从应用程序停止的位置(崩溃之前)继续处理并接收所有过去的事件。更改流可以帮助构建分离且可缩放的体系结构,并使实现提取-转换-加载 (ETL)、通知、同步服务等变得更加容易。

二、应用概述

本文演示了以下应用程序:

  1. 更改流侦听器:它使用监视 API 订阅 MongoDB 集合的更改事件流。创建或更新文档后,此应用程序将立即收到实时通知。它还利用恢复令牌在重新启动或崩溃后从特定时间点继续处理。
  2. REST API:它公开了一个HTTP端点,以便在MongoDB中创建文档。

三、准备工作

  1. 使用本地 Linux 工作站,或将 Vultr 云服务器部署为工作站。
  2. 确保 Docker 已安装在工作站上。您将需要它来构建和运行 Docker 映像。
  3. 在工作站上安装 curl,一个流行的命令行 HTTP 客户端。
  4. 在工作站上安装最新版本的 Go 编程语言(版本 1.18 或更高版本)。

四、准备 MongoDB 更改流应用程序

4.1、初始化项目

创建一个目录并切换到该目录:

mkdir mongo-change-streams

cd mongo-change-streams

创建一个新的 Go 模块:

go mod init mongo-change-streams

这将创建一个新文件go.mod

创建一个新文件:main.go

touch main.go

4.2、导入库

要导入所需的 Go 模块,请将以下内容添加到文件中:main.go

package main



import (

  "context"

  "fmt"

  "log"

  "os"

  "os/signal"

  "syscall"

  "time"



  "go.mongodb.org/mongo-driver/bson"

  "go.mongodb.org/mongo-driver/mongo"

  "go.mongodb.org/mongo-driver/mongo/options"

)

除了 Go 标准库包之外,您还将从 MongoDB Go 驱动程序导入以下包:

  • go.mongodb.org/mongo-driver/mongo– 提供核心的MongoDB功能。
  • go.mongodb.org/mongo-driver/bson– 包 bson 是一个用于读取、写入和操作 BSON 的库。
  • go.mongodb.org/mongo-driver/mongo/options– 包选项定义了MongoDB Go驱动程序的可选配置。

4.3、添加函数init

将以下代码添加到文件中:main.go

var mongoConnectString string

var mongoDatabase string

var mongoCollection string

const msgFormat = "export RESUME_TOKEN=%s"



func init() {

  mongoConnectString = os.Getenv("MONGODB_URI")

  if mongoConnectString == "" {

    log.Fatal("missing environment variable", "MONGODB_URI")

  }



  mongoDatabase = os.Getenv("MONGODB_DATABASE")

  if mongoDatabase == "" {

    log.Fatal("missing environment variable", "MONGODB_DATABASE")

  }



  mongoCollection = os.Getenv("MONGODB_COLLECTION")

  if mongoCollection == "" {

    log.Fatal("missing environment variable", "MONGODB_COLLECTION")

  }

}

该函数分别从 、 和环境变量中检索 MongoDB 连接字符串、集合名称和数据库名称。initMONGODB_URIMONGODB_COLLECTIONMONGODB_DATABASE

4.4、添加函数main

将函数添加到文件:mainmain.go

func main() {

  client, err := mongo.NewClient(options.Client().ApplyURI(mongoConnectString))

  if err != nil {

    log.Fatal("failed to create mongo client", err)

  }



  fmt.Println("created client object")



  ctx, cancel := context.WithCancel(context.Background())



  err = client.Connect(ctx)

  if err != nil {

    log.Fatal("failed to connect to mongo", err)

  }



  fmt.Println("connected to mongodb")



  coll := client.Database(mongoDatabase).Collection(mongoCollection)



  defer func() {

    err = client.Disconnect(context.Background())

    if err != nil {

      fmt.Println("failed to close mongo connection")

    }

  }()



  match := bson.D{{"$match", bson.D{{"operationType", bson.D{{"$in", bson.A{"insert", "update", "replace" }}}}}}}

  project := bson.D{{"$project", bson.M{"_id": 1, "fullDocument": 1, "ns": 1, "documentKey": 1}}}

  pipeline := mongo.Pipeline{match, project}



  opts := options.ChangeStream().SetFullDocument(options.UpdateLookup)



  tokenFromEnv := os.Getenv("RESUME_TOKEN")



  if tokenFromEnv != "" {

    fmt.Println("resume token in enviroment variable", tokenFromEnv)



    t := bson.M{"_data": tokenFromEnv}

    opts.SetResumeAfter(t)



    fmt.Println("set resume token to watch client")

  }



  cs, err := coll.Watch(ctx, pipeline, opts)

  if err != nil {

    log.Fatal("failed to start change stream watch: ", err)

  }



  fmt.Println("watch established")



  defer func() {

    fmt.Println("resume token ", cs.ResumeToken().String())

    fmt.Println("use resume token in the next run with following command -", fmt.Sprintf(msgFormat, cs.ResumeToken().Lookup("_data").StringValue()))



    close, cancel := context.WithTimeout(context.Background(), 5*time.Second)

    defer cancel()



    err := cs.Close(close)

    if err != nil {

      fmt.Println("failed to close change stream")

    }



    fmt.Println("closed change stream")

  }()



  go func() {

    fmt.Println("started change stream...")



    for cs.Next(ctx) {

      re := cs.Current.Index(1)

      fmt.Println("change stream event" + re.Value().String())

    }

  }()



  exit := make(chan os.Signal, 1)

  signal.Notify(exit, syscall.SIGINT, syscall.SIGTERM)



  fmt.Println("waiting for program exit signal")



  <-exit

  fmt.Println("program exit initiated")

  cancel()

}
  • 用于创建新对象。mongo.NewClient*mongo.Client
  • 使用Connect启动与MongoDB的连接。
  • 调用数据库以获取 ,然后调用集合以获取 的句柄。mongo.Databasemongo.Collection
  • 延迟函数用于在程序结束时断开和关闭对象。*mongo.Client
  • A 是使用匹配项目阶段创建的。mongo.Pipeline
  • 如果使用环境变量提供恢复令牌,则用于配置更改流监视客户端。RESUME_TOKEN
  • 获取使用手表。作为程序退出过程的一部分,另一个 defer 函数用于提供恢复令牌信息并关闭更改流。mongo.ChangeStream
  • 更改流侦听器作为 goroutine 启动。它使用 Next 侦听更改流事件,用于获取文档,并将事件记录到控制台。Current.Index
  • 最后,设置一个 Go 通道,以便在程序中断时收到通知并干净地退出。

五、准备 MongoDB REST API 应用程序

创建一个新文件:api.go

touch api.go

5.1、导入库

要导入所需的 Go 模块,请将以下内容添加到文件中:api.go

package main



import (

  "context"

  "fmt"

  "log"

  "net/http"

  "os"

  "strconv"

  "time"



  "go.mongodb.org/mongo-driver/mongo"

  "go.mongodb.org/mongo-driver/mongo/options"

)

除了 Go 标准库包之外,我们还从 MongoDB Go 驱动程序导入以下包:

  • go.mongodb.org/mongo-driver/mongo– 提供核心的MongoDB功能。
  • go.mongodb.org/mongo-driver/mongo/options– 包选项定义了MongoDB Go驱动程序的可选配置。

5.2、添加函数init

将以下代码添加到文件中:api.go

var coll *mongo.Collection

var mongoConnectString string

var mongoDatabase string

var mongoCollection string



func init() {

  mongoConnectString = os.Getenv("MONGODB_URI")

  if mongoConnectString == "" {

    log.Fatal("missing environment variable", "MONGODB_URI")

  }



  mongoDatabase = os.Getenv("MONGODB_DATABASE")

  if mongoDatabase == "" {

    log.Fatal("missing environment variable", "MONGODB_DATABASE")

  }



  mongoCollection = os.Getenv("MONGODB_COLLECTION")

  if mongoCollection == "" {

    log.Fatal("missing environment variable", "MONGODB_COLLECTION")

  }



  client, err := mongo.NewClient(options.Client().ApplyURI(mongoConnectString))

  if err != nil {

    log.Fatal("failed to create mongo client", err)

  }



  fmt.Println("created mongo client object")



  err = client.Connect(context.Background())

  if err != nil {

    log.Fatal("failed to connect to mongo", err)

  }



  fmt.Println("connected to mongo")



  coll = client.Database(mongoDatabase).Collection(mongoCollection)

}

该函数分别从 、 和环境变量中检索 MongoDB 连接字符串、集合名称和数据库名称。它调用数据库方法来获取 ,然后调用集合以获取 .initMONGODB_URIMONGODB_COLLECTIONMONGODB_DATABASEmongo.Databasemongo.Collection

5.3、添加函数main

将函数添加到文件:mainapi.go

func main() {

  http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {



    res, err := coll.InsertOne(context.Background(), map[string]string{"user": "user-" + strconv.Itoa(int(time.Now().Unix()))})

    if err != nil {

      log.Fatal("mongo insert failed", err)

    }



    fmt.Println("created record", res.InsertedID)

  })



  fmt.Println("started http server...")

  log.Fatal(http.ListenAndServe(":8080", nil))

}

main 函数注册一个 HTTP 处理程序,以便在调用时将记录插入到 MongoDB 集合中。HTTP 服务器在端口 8080 上启动。

六、准备 Docker 映像

6.1、添加 Docker 文件

创建一个名为 的文件:Dockerfile.change_stream_app

touch Dockerfile.change_stream_app

在 中输入以下内容:Dockerfile.change_stream_app

FROM golang:1.18-buster AS build



WORKDIR /app

COPY go.mod ./

COPY go.sum ./



RUN go mod download



COPY main.go ./

RUN go build -o /mongodb-app



FROM gcr.io/distroless/base-debian10

WORKDIR /

COPY --from=build /mongodb-app /mongodb-app

EXPOSE 8080

USER nonroot:nonroot

ENTRYPOINT ["/mongodb-app"]
  • 这是一个多阶段,用作第一阶段的基础映像。Dockerfilegolang:1.18-buster
  • 复制应用程序文件,运行 ,然后生成应用程序二进制文件。go mod download
  • 在第二阶段,用作基础映像。gcr.io/distroless/base-debian10
  • 从第一阶段复制二进制文件,并将其配置为运行应用程序。ENTRYPOINT

创建一个名为 的文件:Dockerfile.rest_api

touch Dockerfile.rest_api

在 中输入以下内容:Dockerfile.rest_api

FROM golang:1.18-buster AS build



WORKDIR /app

COPY go.mod ./

COPY go.sum ./



RUN go mod download



COPY api.go ./

RUN go build -o /mongodb-api



FROM gcr.io/distroless/base-debian10

WORKDIR /

COPY --from=build /mongodb-api /mongodb-api

EXPOSE 8080

USER nonroot:nonroot

ENTRYPOINT ["/mongodb-api"]
  • 这是一个多阶段,用作第一阶段的基础映像。Dockerfilegolang:1.18-buster
  • 复制应用程序文件,运行 ,然后生成应用程序二进制文件。go mod download
  • 在第二阶段,用作基础映像。gcr.io/distroless/base-debian10
  • 从第一阶段复制二进制文件,并将其配置为运行应用程序。ENTRYPOINT

6.2、构建 Docker 镜像

拉动模块:

go mod tidy

为更改流应用程序构建 Docker 映像:

docker build -t mongo-change-streams -f Dockerfile.change_stream_app .

为 REST API 应用程序构建 Docker 镜像:

docker build -t mongo-rest-api -f Dockerfile.rest_api .

 七、在 Docker 中启动 MongoDB 集群

创建一个 Docker 网络:

docker network create mongodb-cluster

启动第一个节点 mongo1

docker run -d --rm -p 27017:27017 --name mongo1 --network mongodb-cluster mongo mongod --replSet myReplicaSet --bind_ip localhost,mongo1

启动第二个节点 mongo2

docker run -d --rm -p 27018:27017 --name mongo2 --network mongodb-cluster mongo mongod --replSet myReplicaSet --bind_ip localhost,mongo2

启动第三个节点 mongo3

docker run -d --rm -p 27019:27017 --name mongo3 --network mongodb-cluster mongo mongod --replSet myReplicaSet --bind_ip localhost,mongo3

配置副本集:

docker exec -it mongo1 mongosh --eval "rs.initiate({

_id: \"myReplicaSet\",

members: [

  {_id: 0, host: \"mongo1\"},

  {_id: 1, host: \"mongo2\"},

  {_id: 2, host: \"mongo3\"}

]

})"

您应该看到以下输出:

{ ok: 1 }

 八、启动两个应用程序

在终端中,启动更改流应用程序:

export MONGODB_URI=mongodb://mongo1:27017,mongo2:27017,mongo3:27017/?replicaSet=myReplicaSet



docker run --network mongodb-cluster -e MONGODB_URI=$MONGODB_URI -e MONGODB_DATABASE=test_db -e MONGODB_COLLECTION=test_collection -e RESUME_TOKEN=$RESUME_TOKEN mongo-change-streams

您将看到类似于以下内容的输出:

created client object

connected to mongodb

watch established

started change stream...

waiting for program exit signal

在另一个终端中,启动 REST API 应用程序:

export MONGODB_URI=mongodb://mongo1:27017,mongo2:27017,mongo3:27017/?replicaSet=myReplicaSet



docker run --network mongodb-cluster -p 8080:8080 -e MONGODB_URI=$MONGODB_URI -e MONGODB_DATABASE=test_db -e MONGODB_COLLECTION=test_collection mongo-rest-api

您将看到类似于以下内容的输出:

created mongo client object

connected to mongo

started http server...

 九、测试应用程序

在MongoDB中创建一些记录。为此,调用 REST API 应用程序(从另一个终端)公开的 HTTP 端点:

curl -i localhost:8080

重复上述过程两到三次。在所有情况下,您都应该得到HTTP / 1.1 200 OK响应。

导航到终端并检查 REST API 应用程序日志。您应该会看到已创建的记录。请注意,在您的情况下,对象 ID 可能有所不同:

created record ObjectID("639c092160078afff212209b")

created record ObjectID("639c097660078afff212209c")

created record ObjectID("639c097760078afff212209d")

导航到终端并检查更改流应用程序日志。您应该看到与上述相同的记录(由 REST API 应用程序创建)。这些是由更改流侦听器进程自动检测到的。请注意,在您的情况下,对象 ID 可能有所不同:

change stream event{"_id": {"$oid":"639c092160078afff212209b"},"user": "user-1671170337"}

change stream event{"_id": {"$oid":"639c097660078afff212209c"},"user": "user-1671170422"}

change stream event{"_id": {"$oid":"639c097760078afff212209d"},"user": "user-1671170423"}

9.1、使用更改流恢复令牌

首先,关闭更改流应用程序 – 在运行该应用程序的相应终端上按 +。CTRLC

您应该会看到与此类似的日志。请注意,令牌可能因您的情况而异。

resume token  {"_data": "82639C09A4000000012B0229296E04"}

use this token in the next run with following command - export RESUME_TOKEN=82639C09A4000000012B0229296E04

日志消息突出显示了如果要利用 Resume 令牌时应使用的命令。记下该命令。

通过调用 REST API 应用程序公开的 HTTP 端点向 MongoDB 添加一些记录:

curl -i localhost:8080

重复几次。

导航到终端并检查 REST API 应用程序日志。您应该会看到已创建的记录。请注意,在您的情况下,对象 ID 可能有所不同:

created record ObjectID("639c09ed60078afff212209e")

created record ObjectID("639c09ee60078afff212209f")

重新启动更改流应用程序。这一次,通过将 Resume 令牌作为环境变量传递来使用它。您可以使用上面的日志输出中的命令:

export RESUME_TOKEN=82639C09A4000000012B0229296E04



export MONGODB_URI=mongodb://mongo1:27017,mongo2:27017,mongo3:27017/?replicaSet=myReplicaSet



docker run --network mongodb-cluster -e MONGODB_URI=$MONGODB_URI -e MONGODB_DATABASE=test_db -e MONGODB_COLLECTION=test_collection -e RESUME_TOKEN=$RESUME_TOKEN mongo-change-streams

您应该会看到与此类似的日志。请注意,令牌和对象 ID 在您的情况下可能会有所不同。

token passed in as enviroment variable 82639C09A4000000012B0229296E04

set token to watch client option

watch established

started change stream...

change stream event{"_id": {"$oid":"639c09ed60078afff212209e"},"user": "user-1671170541"}

change stream event{"_id": {"$oid":"639c09ee60078afff212209f"},"user": "user-1671170542"}

验证您收到的记录是否与关闭更改流应用程序时添加的记录相同。

您可以通过调用 REST API 应用程序公开的 HTTP 端点来继续向 MongoDB 添加记录:

curl -i localhost:8080

正如预期的那样,更改流应用程序将实时检测和记录这些:

您应该看到类似于以下内容的日志:

change stream event{"_id": {"$oid":"639c0a5c60078afff21220a0"},"user": "user-1671170652"}

change stream event{"_id": {"$oid":"639c0a5d60078afff21220a1"},"user": "user-1671170653"}

 十、收尾

最后,要停止这两个应用程序,请在各自的终端中按 +。CTRLC

同时删除 MongoDB 集群实例和 Docker 网络:

docker rm -f mongo1 mongo2 mongo3

docker network rm mongodb-cluster

 十一、结论

在本文中,您将了解 MongoDB 和更改流的概述。您在 Docker 中设置了一个 MongoDB 副本集,部署了客户端应用程序,并通过端到端示例探索了更改流和恢复令牌。

如何在 Python 中使用 MongoDB 与 MongoEngine

一、介绍

MongoDB是一个免费的开源NoSQL数据库程序。它将数据存储在文档集合中,其中文档类似于传统关系数据库系统中的一行。它没有用于在集合中存储数据的固定架构;您可以将数据存储在键值对中,就像 Python 字典一样。灵活的数据模型和对水平扩展的支持等功能允许您在需求更改时进行更改或缩放数据库。

MongoEngine是一个对象文档映射器(ODM),它允许你的Python应用程序与MongoDB数据库进行交互。它提供了一个声明性 API,您可以在其中使用 Python 类和对象与数据库中的文档进行交互。这个抽象层使开发人员更容易与MongoDB数据库进行交互,有助于减少开发时间,并使数据库逻辑不易出错。

本文介绍 MongoEngine ODM 的安装和配置,定义文档架构、执行创建、读取、更新和删除 (CRUD) 操作以及从数据库中查询筛选数据的步骤。它还介绍了文档引用、迁移和元选项的基础知识。

二、准备工作

  • 在 Vultr 部署 Ubuntu 20.04 实例。
  • 创建具有 sudo 权限的非 root 用户。
  • 以非根用户身份登录您的实例。
  • 在实例上安装 MongoDB 数据库服务器。

三、设置环境

安装 MongoEngine 库。

$ pip install mongoengine

设置新的项目目录。

$ mkdir ~/mongoengine_demo

切换到项目目录。

$ cd ~/mongoengine_demo

 四、连接到数据库

您可以使用 MongoEngine 模块中的函数与 MongoDB 服务器建立连接。必须将主机名、端口、数据库等值作为参数传递。connect()

使用文本编辑器创建一个名为 的新 Python 文件。app.py

$ nano app.py

将以下内容添加到文件中,并使用 + 然后保存文件。CTRLXENTER

from mongoengine import *

client = connect('mongoengine_demo')

上面的代码使用默认主机和端口与MongoDB服务器建立连接。作为参数传递的字符串引用数据库的名称。如果数据库不存在,它会尝试使用传递给函数的名称创建新数据库。127.0.0.127017connect()

以下示例演示如何使用非默认值连接到 MongoDB 服务器。

connect('database_name', username='username', password='password', authentication_source='admin')

还可以使用该参数与多个数据库或数据库服务器建立连接。有关详细信息,请参阅 MongoEngine 文档中的多个数据库部分。alias

五、定义文档架构

存储在MongoDB数据库中的文档没有任何固定的模式。但是,定义文档架构可确保数据结构和验证,从而使数据库逻辑不易出错。

MongoEngine ODM允许您创建固定或动态文档架构。您可以从 MongoEngine 模块继承 or 类以创建新的文档类并使用字段对象定义每个字段,请参阅 MongoEngine 文档中的字段部分以查找所有可用的字段类型。DocumentDynamicDocument

编辑在上一节中创建的 Python 文件。

$ nano app.py

将以下内容添加到文件中,并使用 + 然后保存文件。CTRLXENTER

class User(Document):
    name = StringField(required=True)
    email = EmailField(required=True)
    age = IntField(required=True)

    def __repr__(self):
        return f'<User name="{self.name}">'

上面的代码创建了一个名为继承自 MongoEngine 模块中的类的文档类。它将 Python 类映射到数据库中的集合。默认情况下,它使用转换为蛇大小写的 Python 类名作为集合名称。此文档类使用固定架构,其中对象只能包含名称、电子邮件和期限。UserDocument

六、执行 CRUD 操作

MongoEngine 将每个文档类映射到数据库中的集合。创建文档类的新实例以在集合中创建新文档。本节介绍如何使用上一节中创建的文档类执行 CRUD 操作。

进入Python控制台。

$ python

导入所需的模块。

>>> from app import User

上面的命令从您在上一节中创建的 Python 文件中导入类。User

创建新条目。

>>> user1 = User(name='Example User', email=f'user@example.com', age=21)
>>> user1.save()

上面的命令从类创建一个新对象并调用该方法,该方法启动集合并在数据库中创建新文档。Usersave()

阅读第一个条目。

>>> User.objects.first()

上面的命令返回一个字典,其中包含存储在集合中的第一个文档的值。user

更新条目。

>>> user1.age = 22
>>> user1.save()

上面的命令更改对象中 age 属性的值并调用该方法,该方法将更新数据库中的文档。user1save()

验证更改。

>>> User.objects.first().age

删除条目。

>>> user1.delete()

验证更改。

>>> User.objects

退出 Python 控制台。

>>> exit()

 七、查询筛选后的数据

文档类具有允许访问存储在集合中的对象的属性。该属性是一个接受条件并返回包含筛选的文档对象的对象。本节介绍使用文档类查询筛选数据的基础知识。objectsobjectsQuerySetManagerQuerySet

进入Python控制台。

$ python

导入所需的模块。

>>> from app import User

填充数据库。

>>> user_objects = [User(name=f'Person {i}', email=f'person{i}@example.com', age=i+18) for i in range(10)]
>>> User.objects.insert(user_objects)

上述命令使用枚举值创建 10 个不同对象的列表,并将其插入到数据库中。User

使用单个条件查询文档。

>>> User.objects(age__gt=20)

上面的命令返回年龄超过 20 的文档列表。

输出

[<User name="Person 3">, <User name="Person 4">, <User name="Person 5">, <User name="Person 6">, <User name="Person 7">, <User name="Person 8">, <User name="Person 9">]

使用多个条件查询文档。

>>> User.objects(age__gt=20, age__lt=25)

上面的命令返回年龄大于 20 且小于 25 的文档列表。

输出

[<User name="Person 3">, <User name="Person 4">, <User name="Person 5">, <User name="Person 6">]

获取单个文档。

>>> User.objects(age__=19).first()

上面的命令返回一个生存期为 19 的文档对象。该方法返回单个文档对象,而不是包含文档对象的列表。first()

输出

<User name="Person 1">

退出 Python 控制台。

>>> exit()

请参阅 MongoEngine 文档中的查询数据库,以查找 中的所有可用过滤选项。QuerySetManager

 八、文档参考

MongoEngine ODM允许链接到文档架构中的其他文档。它使您能够在文档之间创建关系;与传统的关系数据库系统一样,它们将链接行的主键存储为外键。

您可以使用文档架构中的字段对象链接到其他文档。MongoEngine ODM 还支持 和 字段对象的组合以形成多对一关系。ReferenceFieldListFieldReferenceField

本节介绍如何使用文档类中的字段对象链接到不同的文档。ReferenceField

编辑 Python 文件。

$ nano app.py

将以下内容添加到 User 文档类上方的文件中,并使用 + 然后保存文件。CTRLXENTER

class Video(Document):
    title = StringField(required=True)

    def __repr__(self):
        return f'<Video title="{self.title}">'

class Course(Document):
    name = StringField(required=True)
    price = IntField(required=True)
    videos = ListField(ReferenceField(Video))

    def __repr__(self):
        return f'<Course name="{self.name}">'

上面的代码创建 Python 类,并从在数据库中创建两个新集合的类继承。文档类使用 and 字段对象在 videos 属性中存储视频对象引用的列表。VideoCourseDocumentCourseReferenceFieldListField

进入 Python 控制台。

$ python

导入所需的模块。

>>> from app import Course, Video

上面的命令从文件中导入 and 类。CourseVideoapp.py

视频集合中创建新条目。

>>> video1 = Video(title='Example Video 1').save()
>>> video2 = Video(title='Example Video 2').save()

上述命令创建文档类的两个新实例,该实例在数据库中启动并创建两个新文档。Video

课程集合中创建新条目。

>>> course1 = Course(name='Example Course 1', price=100, videos=[video1, video2]).save()

上面的命令创建文档类的新实例,该实例初始化并在数据库中创建新文档。它将文档与视频集合中的其他两个文档链接。Course

验证更改。

>>> Course.objects.first().videos
>>> Course.objects.first().videos[0].title
>>> Course.objects.first().videos[1].title

退出 Python 控制台。

>>> exit()

 九、文档迁移

NoSQL 数据库的灵活性使您可以轻松地进行文档架构更改。本节介绍如何在文档架构中进行结构更改。

编辑 Python 文件

$ nano app.py

将以下内容添加到文件中,并使用 + 然后保存文件。CTRLXENTER

class User(Document):
    name = StringField(required=True)
    email = EmailField(required=True)
    age = IntField(required=True)
    enrolled_courses = ListField(ReferenceField(Course))

    def __repr__(self):
        return f'<User name="{self.name}">'

上面的代码修改在用户集合中添加了一个名为 enrolled_courses 的新属性。和字段对象的组合允许用户文档引用多个课程文档。ListFieldReferenceField

进入Python控制台。

$ python

导入所需的模块。

>>> from app import User, Course

上面的命令从文件中导入 and 类。UserCourseapp.py

获取文档对象。

>>> user1 = User.objects.first()
>>> course1 = Course.objects.first()

上述命令从用户课程集合中获取第一个文档对象。

更新用户文档对象。

>>> user1.enrolled_courses = [course1]
>>> user1.save()

上述命令将 enrolled_courses 属性的值设置为包含文档引用对象的 Python 列表。Course

验证更改。

>>> User.objects.first().enrolled_courses
>>> User.objects.first().enrolled_courses[0].name

退出 Python 控制台。

>>> exit()

文档架构中的更改不会影响现有文档。如果要将更改应用于所有文档,则必须对集合使用该方法。有关更多信息,请参阅 MongoEngine 文档中的文档迁移部分。update_many()

十、文档元选项

文档类中的字典允许您向集合添加元数据,例如集合名称、文档索引列表、默认排序和继承选项、分片键等。本节介绍字典在文档类中的用法。metameta

编辑 Python 文件

$ nano app.py

将以下内容添加到 User 文档类下面的文件中,并使用 + then 保存文件。CTRLXENTER

class MetaExample(Document):
    age = IntField()

    meta = {
        'collection': 'example_collection',
        'indexes': ['age']
    }

    def __repr__(self):
        return f'<MetaExample age={self.age}>'

上面的代码创建了一个名为从该类继承的新 Python 类。它会创建一个名为 example_collection 的新集合,并在集合索引中添加年龄字段。MetaExampleDocument

索引是一种特殊的数据结构,它存储存储在数据库中的数据子集,使数据更易于以编程方式横向。如果没有索引,服务器必须执行完全集合扫描。如果查询存在适当的索引,则服务器可以限制必须扫描的文档数。

进入Python控制台。

$ python

导入所需的模块。

>>> from app import client, MetaExample

上面的命令从文件中导入对象和类。clientMetaExampleapp.py

初始化集合。

>>> MetaExample(age=999).save()

验证自定义集合名称。

>>> client.get_database('mongoengine_demo').list_collection_names()

验证集合索引。

>>> MetaExample.list_indexes()

退出 Python 控制台。

>>> exit()

请参阅 MongoEngine 文档中的文档集合部分,以查找可用元选项的完整列表。

十一、结论

您安装了 MongoEngine 库,与 MongoDB 数据库服务器建立了连接,定义了文档架构,执行了 CRUD 操作,并从数据库中查询了过滤的数据。您还探索了文档引用、迁移和元选项的基础知识。

如何创建 MongoDB 副本集

一.介绍

在任务关键型应用程序中部署 MongoDB 数据库时,可以配置副本集以实现高可用性。副本集提供冗余和高可用性,由于没有单点故障,因此可减少灾难期间的停机时间。MongoDB 副本集的最低建议配置是一个主节点和两个辅助节点,但副本集最多可以有 50 个成员。应用程序仅写入主节点,辅助节点复制数据。如果主节点发生故障,副本集将举行选举以选择新的主节点。应用程序可以从辅助数据库读取数据,但不能写入它们。

本指南介绍如何创建 MongoDB 副本集。它在 Ubuntu 20.04 上进行了测试,但其他 Linux 发行版的步骤类似。

二.准备工作

您需要将三台服务器连接到同一个 Vultr VPC。每个服务器都应具有:

  • 配置了 sudo 权限的非 root 用户
  • MongoDB安装并使用密码保护
  • 为清楚起见,本指南对服务器使用以下主机名和专用 IP 地址。您应该用您的值替换这些值。
    • 主:服务器-1 – 10.0.0.1
    • 辅助:服务器-2 – 10.0.0.2
    • 辅助:服务器-3 – 10.0.0.3

三 配置主机文件

MongoDB建议使用DNS主机名而不是副本成员的IP地址。由于 Vultr VPC 是没有 DNS 的私有网络,因此请将私有 IP 地址和主机名添加到主机文件中。在每台服务器上重复这些步骤。

  1. 以非 root 用户身份通过 SSH 连接到服务器。
  2. 编辑主机文件。
    $ sudo nano /etc/hosts
  3. 找到下面的行。
    127.0.0.1 localhost
  4. 输入 IP 地址和主机名,如该行下所示。
    127.0.0.1 localhost
    10.0.0.1 server-1
    10.0.0.2 server-2
    10.0.0.3 server-3
  5. 保存并关闭文件。

四. 设置复制密钥

副本集中的所有服务器共享一个 base64 密钥。请按照以下步骤安装密钥。

使用该命令在其中一台服务器上生成新密钥。openssl

$ openssl rand -base64 756

你应该得到这样的块。复制此 base64 密钥。您将在以下步骤中使用它。

Yga80PbkHKptRRoONFCPaPzOCFpySgpwNHMA3JS179wyGCOIOYg/FUnDyiIhGe5D
YVQF3o+SliscBiKftsPZ5WBojRREcefAUHOqK7pVBOjT+oYuH6ltMGiDtH26XjVB
... truncated ...
yxJm+UjpN0n8V1pH1LrMJT4FC4Bw3L7vqSnxVbLRnQIiO2Y0ECfyPgepCCNIyuaP
mMSUJ8mmlq4jdfoAKvCspeliSQ/cqaxKfqaTWjzhsLk8eHbU

在每台服务器上重复这些步骤。

  1. 创建新的auth_key文件。
    $ sudo nano /var/lib/mongodb/auth_key
  2. 粘贴您的 base64 密钥。
  3. 保存并关闭文件。
  4. 将权限设置为 400,使文件对文件所有者只读,对所有其他文件都被拒绝访问。
    $ sudo chmod 400 /var/lib/mongodb/auth_key
  5. 将所有者和组更改为 mongodb
    $ sudo chown mongodb:mongodb /var/lib/mongodb/auth_key

 五. 配置 MongoDB

在本部分中,你将配置共享密钥、网络接口和副本集名称。在每台服务器上重复这些小节。

5.1. 配置共享密钥

  1. 在编辑器中打开 mongod.conf 以执行以下步骤。
    $ sudo nano /etc/mongod.conf
  2. 找到安全部分。
    security:
      authorization: enabled
    #operationProfiling:
  3. 授权:行下,添加键文件值,如下所示。
    security:
      authorization: enabled
      keyFile: /var/lib/mongodb/auth_key
    #operationProfiling:

5.2. 配置网络接口

  1. 找到网络接口部分。
    # network interfaces
    net:
      port: 27017
      bindIp: 127.0.0.1
  2. 将环路接口 (127.0.0.1) 之后的相应服务器名称添加到每个服务器。例如:在服务器 1 上:
    # network interfaces
    net:
      port: 27017
      bindIp: 127.0.0.1, server-1

    在服务器 2 上:

    # network interfaces
    net:
      port: 27017
      bindIp: 127.0.0.1, server-2

    在服务器 3 上:

    # network interfaces
    net:
      port: 27017
      bindIp: 127.0.0.1, server-3

5.3. 配置副本集名称

  1. 找到复制部分。
    #replication:
  2. 从复制行中删除注释。在此下方,按所示添加。#replSetName: "rs0"
    replication:
      replSetName: "rs0"
  3. 在主节点上重新启动 MongoDB。
    $ sudo systemctl restart mongod
  4. 在辅助节点上重新启动 MongoDB。
    $ sudo systemctl restart mongod

 六. 引导副本集

在本部分中,你将节点添加到副本集并引导复制过程。

  1. 在主节点上,登录到MongoDB。
    $ mongosh -u your_admin_name -p --authenticationDatabase admin
  2. 输入您的管理员帐户的密码,然后按继续。ENTER
  3. 运行以下命令以添加副本集成员。
    test> rs.initiate(
          {
          _id: "rs0",
          members: [
              { _id: 0, host: "server-1" },
              { _id: 1, host: "server-2" },
              { _id: 2, host: "server-3" }
              ]
          })
  4. 当副本集启动时,应收到以下响应。请注意,提示符更改为 。rs0 [direct: secondary] test>
    { ok: 1 }
    rs0 [direct: secondary] test>
  5. 创建示例company_db数据库。
    rs0 [direct: secondary] test> use company_db
  6. 您应该会收到以下响应,提示更改为 。此成员现在是主节点。rs0 [direct: primary] company_db>
    switched to db company_db
    rs0 [direct: primary] company_db>
  7. company_db数据库的新员工集合中插入示例记录。
    rs0 [direct: primary] company_db> db.employees.insertOne({   
                                      "staff_id" : 1,
                                      "staff_name" : "JOHN DOE",
                                      "phone" : "11111111"  
                                      })
  8. 您应该得到下面的输出。
    {
      acknowledged: true,
      insertedId: ObjectId("621dcf1abdb5b0c5e59294d9")
    }
  9. 在每个辅助节点上,登录到MongoDB。
    $ mongosh -u your_admin_name -p --authenticationDatabase admin
  10. 输入您的管理员帐户的密码,然后按继续。ENTER
  11. 您应该会看到下面的提示,显示成员是辅助节点。
    rs0 [direct: secondary] test>
  12. 在每个辅助节点上,切换到company_db
    rs0 [direct: secondary] test> use company_db
  13. 应得到以下输出。
    switched to db company_db
  14. 在每个辅助节点上运行以下命令,以允许它们接受读取命令。
    rs0 [direct: secondary] company_db> db.getMongo().setReadPref('primaryPreferred')
  15. 列出员工集合中的文档。
    rs0 [direct: secondary] company_db> db.employees.find()
  16. 您应该在每个辅助节点上获得以下输出,该输出显示副本集将数据复制到每个节点。
    [
      {
        _id: ObjectId("621dcf1abdb5b0c5e59294d9"),
        staff_id: 1,
        staff_name: 'JOHN DOE',
        phone: '11111111'
      }
    ]
  17. 尝试在任何辅助节点上添加新的员工记录。
    rs0 [direct: secondary] company_db> db.employees.insertOne({   
                                      "staff_id" : 2,
                                      "staff_name" : "MARY ROE",
                                      "phone" : "22222222"  
                                      })
  18. 该命令应失败。辅助节点是只读的。
    MongoServerError: not primary
  19. 如果停止主服务器或主服务器脱机,副本集将选择其中一个辅助节点作为新的主节点。
    $ sudo systemctl stop mongod

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

1.介绍

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

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

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

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

2.准备工作

要继续执行本指南,请确保您已获得以下各项:

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

3. 创建 MongoDB 数据库

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

  1. 登录到您的MongoDB数据库。替换为数据库的管理员帐户。mongo_db_admin
    $ mongosh -u mongo_db_admin -p --authenticationDatabase admin
  2. 出现提示时,输入MongoDB帐户的密码,然后按继续。接下来,运行下面的语句以创建数据库。ENTERshop_db
    test> use shop_db
  3. 确认已切换到新数据库。shop_db
    switched to db shop_db
  4. 接下来,使用 MongoDB 函数在新集合中插入三个文档。productsinsertMany()
    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. 现在,您已经设置了数据库集合和示例文档。在接下来的步骤中,您将使用 Golang 语言创建一些脚本来操作您的 MongoDB 集合。shop_dbproducts

4. 创建文件main.go

该文件将保存应用程序的函数。这是执行应用程序时触发的主要方法。main.gomain()

  1. 在创建文件的源代码之前,请创建一个目录以将源代码与其余 Linux 文件分开。main.goproject
    $ mkdir project
  2. 然后,切换到新目录。project
    $ cd project
  3. 接下来,使用文本编辑器打开一个新文件以进行编辑。nanomain.go
    $ nano main.go
  4. 打开文件后,在文件中输入以下信息。将 替换为 MongoDB 用户帐户的正确值。main.gomongo_db_adminEXAMPLE_PASSWORD
    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. 完成编辑后保存并关闭文件。
  6. 在上面的文件中,您将创建一个 Web 服务器,该服务器使用语句和 .8080http.HandleFunc("/api/v1/products", requestHandler)http.ListenAndServe(":8080", nil)
  7. 在该函数下,您将连接到之前创建的 MongoDB 实例。接下来,使用 Golang 语句通过传递集合引用将 HTTP 请求路由到相应的 CRUD 函数。最后,您将使用 JSON 函数以人类可读的格式格式化和输出数据。requestHandler()switchproducts
  8. 创建文件后,现在将在不同的文件上设置单独的函数,以处理应用程序的所有 CRUD 操作。main.go

5. 设置新文件create_record.go

要为 CRUD 操作设置的第一个文件是该文件。此文件包含用于将文档插入集合的功能。create_record.goproducts

  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. 保存并关闭文件。
  4. 上面文件中的主要功能是将BSON有效负载从请求HTTP客户端保存到MongoDB数据库。在上述文件下,如果语句执行没有任何错误,则返回新文档的 。collection.InsertOne(ctx, data)insertedId
  5. 接下来,您将设置一个函数来从 MongoDB 集合中删除文档。

6. 创建文件delete_record.go

与任何其他应用程序一样,如果不再需要记录,则必须提供从集合中删除记录的功能。products

  1. 使用 打开一个新文件 。delete_record.gonano
    $ 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. 保存并关闭文件。
  4. 在上面的文件中,您正在使用该函数从MongoDB数据库中删除文档。为了确保删除正确的文档,请使用语句检索要删除的项目。换句话说,在向应用程序提交请求时,您应该在 HTTP 有效负载中传递 a。collection.DeleteOne(...)product_idbson.M{"product_id": data["product_id"]}product_idDELETE
  5. 接下来,您将设置一个函数来更新文档。

7. 创建一个新文件update_record.go

您将使用该文件对文档进行更改。此文件下的 function() 依赖于包含要更新的字段的有效负载以及文档的唯一性。update_record.goupdateRecord()product_id

  1. 用于打开新文件。nanoupdate_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. 在上面的文件中,您首先使用语句为要更新的文档提供一个参数。然后,您将使用语句提交新的文档值。此处的值来自请求客户端提交的 HTTP 有效负载。filterfilter := bson.M{"product_id": data["product_id"]}fields := bson.M{"$set": data}data
  4. 接下来,使用该函数向集合提交更新请求。在下一步中,您将创建一个函数,用于从 MongoDB 集合中检索记录。collection.UpdateOne(ctx, filter, fields)

8. 创建一个新文件get_records.go

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

  1. 用于创建新文件。nanoget_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. 保存并关闭文件。
  4. 在上面的文件中,您将使用该函数返回已保存在集合中的文档的光标。然后,您将使用循环循环访问稍后附加到数组的文档。cur, err := collection.Find(ctx, bson.D{})productsfor cur.Next(ctx) {...}products []bson.M
  5. 最后,您将数据作为映射返回到调用函数。现在,你已为应用设置了所有 CRUD 函数。在下一步中,您将测试应用程序以确保一切按预期工作。[string]interface{}

9. 测试 Golang 应用程序

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

  1. 导入 Golang 应用程序的 MongoDB 驱动程序。
    $ go get go.mongodb.org/mongo-driver/mongo
  2. 接下来,执行以下命令以运行应用程序。以下命令允许应用程序启动 Web 服务器并侦听端口上的传入 HTTP 连接,并具有阻止功能。不要在此 SSH 终端窗口上运行任何其他命令。8080
    $ 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. 现在,您应该会看到四个文档的列表。前三个是首次初始化数据库时设置的文档,最后一个 record() 是您刚刚使用该命令插入的文档。WIRELESS KEYBOARDcurl
    {
    
      "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. 接下来,运行以下命令以使用 of 更新文档并将其 from 更改为 。product_id1product_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. 通过运行以下命令删除带有 of () 的文档。product_id4WIRELESS KEYBOARD
    $ curl -X DELETE localhost:8080/api/v1/products -H "Content-Type: application/json" -d '{"product_id": 4}'
  11. 您应该会收到以下确认消息。
    {
    
      "data": "Document deleted successfully."
    
    }
  12. 接下来,再次检索记录,以确保已在集合中执行 和 操作。UPDATEDELETEproducts
    $ curl -X GET localhost:8080/api/v1/products
  13. 从下面的输出中可以看到,您已经删除了带有 of 的文档,并且您还成功地将文档的值更新为 of 到 。product_id4product_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 操作。

10.结论

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

如何在 Debian 11 上安装 MongoDB

一、介绍

MongoDB是一个NoSQL数据库应用程序,用于将数据作为类似JSON的文档存储在服务器上。MongoDB拥有现代化的基础设施,具有各种服务,同时具有延展性和友好性,为开发人员及其代码提供了自由。

  • 跨平台
  • 可选架构
  • 各种安全和加密功能
  • 易于实施

本指南将解释如何在 Debian 11 实例上安装和配置 MongoDB 基础知识。

二、准备工作

  • 部署 Debian 11 实例。
  • 使用 sudo 用户登录到实例。

三、安装 MongoDB

安装用于安装 MongoDB 的其他软件包。

$ sudo apt install gnupg2 wget

添加 MongoDB 公共 GPG 密钥。

$ wget -qO - https://www.mongodb.org/static/pgp/server-5.0.asc | sudo apt-key add -

将 MongoDB 的存储库添加到您的实例中。

$ echo "deb http://repo.mongodb.org/apt/debian buster/mongodb-org/5.0 main" | sudo tee /etc/apt/sources.list.d/mongodb-org-5.0.list

更新您的实例。

$ sudo apt update

安装 MongoDB。

$ sudo apt install mongodb-org

验证 MongoDB 是否已成功安装。

$ mongod --version



db version v5.0.6

    Build Info: {

        "version": "5.0.6",

        "gitVersion": "212a8dbb47f07427dae194a9c75baec1d81d9259",

        "openSSLVersion": "OpenSSL 1.1.1k  25 Mar 2021",

        "modules": [],

        "allocator": "tcmalloc",

        "environment": {

        "distmod": "debian10",

        "distarch": "x86_64",

        "target_arch": "x86_64"

    }

}

启动 MongoDB 服务。

$ sudo systemctl start mongod

启用 MongoDB 以在实例启动时启动。

$ sudo systemctl enable mongod

 四、创建新用户

在MongoDB的环境中创建用户对于在特定数据库中授权自己和访问MongoDB中的功能非常简单有用。

输入MongoDB的shell,Mongosh。您可以连接到MongoDB部署。但是,在本指南中,我们将连接到在本地主机上运行的MongoDB实例。

$ sudo mongosh

默认情况下,您将使用测试数据库。您可以通过输入Mongosh来显示您正在使用的数据库。让我们将数据库切换到管理数据库。db

$ use admin

要创建新用户,请在 Mongosh 中输入此代码块。您可以添加自己唯一的用户名和密码

db.createUser(

    {

        user: "Vultr",

        pwd:  "topSecret1",

        roles: [ { role: "userAdminAnyDatabase", db: "admin" } ]

    }

)

成功创建新用户后,Mongosh 会提示以下输出。

{ ok: 1 }

显示数据库上的可用用户。

> show users

[

    {

        _id: 'admin.Vultr',

        userId: UUID("697f43de-6542-4a3c-b846-fbb3ad9f766b"),

        user: 'Vultr',

        db: 'admin',

        roles: [ { role: 'userAdminAnyDatabase', db: 'admin' } ],

        mechanisms: [ 'SCRAM-SHA-1', 'SCRAM-SHA-256' ]

    }

 ]

您可以通过按 + 两次、+ 或输入 Mongosh 来退出 Mongosh。CTRLCCTRLD.exit

五、启用数据库身份验证

MongoDB的标准是在使用数据库时禁用身份验证。为了保护您的数据库,在MongoDB中启用用户身份验证至关重要。

使用所需的文本编辑器输入MongoDB配置文件。

$ sudo nano /etc/mongod.conf

将此代码块粘贴到 MongoDB 配置文件中以启用身份验证。

security:

 authorization: enabled

保存并退出配置文件,然后重新启动MongoDB。

$ sudo systemctl restart mongod

输入Mongosh与您的用户名和密码。

$ sudo mongosh -u Vultr -p topSecret1

成功进行身份验证后,Mongosh 会提示以下输出。

Current Mongosh Log ID: 61fff39bf56ab6dd6b893038

Connecting to: mongodb://127.0.0.1:27017/directConnection=true&serverSelectionTimeoutMS=2000&appName=mongosh+1.1.9

Using MongoDB:          5.0.6

Using Mongosh:          1.1.9



For mongosh info see: https://docs.mongodb.com/mongodb-shell/



>