注:本博文展示部署哥操作步骤和命令,具体报告及运行截图可通过上方免费资源绑定下载
一.数据库的部署与配置
1.单MongoDB服务器的部署
(1)将服务器、客户端和工具安装包上传到hadoop1的/export/software目录
(2)使用解压缩命令:
·tar -xzf /export/software/mongodb-linux-x86_64-rhel90-7.0.15.tgz -C /export/servers/
·tar -xzf /export/software/mongosh-2.3.3-linux-x64.tgz -C /export/servers/
·tar -xzf /export/software/mongodb-database-tools-rhel93-x86_64-100.10.0.tgz -C /export/servers/
对以上三个压缩包进行解压缩至/export/servers目录下
(3)创建数据库数据存储目录和日志文件:
· mkdir -p /export/data/mongodb/db/data
· mkdir -p /export/data/mongodb/db/logs
· touch /export/data/mongodb/db/logs/1.log
- 进入MongoDB服务器目录:
· cd /export/servers/mongodb-linux-x86_64-rhel90-7.0.15/bin
(5)启动服务:
· ./mongod --dbpath /export/data/mongodb/db/data/ --logpath /export/data/mongodb/db/logs/1.log --bind_ip ****hadoop1 --port 27017 --fork,****显示"child process started successfully",证明启动成功
(6)在客户端使用下面命令登录服务器:
· cd /export/servers/mongosh-2.3.3-linux-x64/bin
· ./mongosh --host hadoop1:27017
2.MongoDB复制集的部署
2.1 单机部署
(1)创建存放MongoDB副本集数据的目录:
· mkdir -p /export/data/mongodb/replicaset1/data
· mkdir -p /export/data/mongodb/replicaset2/data
· mkdir -p /export/data/mongodb/replicaset3/data
(2)创建存放MongoDB副本集日志的目录:
· mkdir -p /export/data/mongodb/replicaset1/logs
· mkdir -p /export/data/mongodb/replicaset2/logs
· mkdir -p /export/data/mongodb/replicaset3/logs
(3)在MongoDB副本集日志的目录下创建日志文件:
· touch /export/data/mongodb/replicaset1/logs/mongodb.log
· touch /export/data/mongodb/replicaset2/logs/mongodb.log
· touch /export/data/mongodb/replicaset3/logs/mongodb.log
(4)以副本集的方法启动MongoDB:
· cd /export/servers/mongodb-linux-x86_64-rhel90-7.0.15/bin
· ./mongod --replSet test_replica_set --dbpath=/export/data/mongodb/replicaset1/data/ --logpath=/export/data/mongodb/replicaset1/logs/mongodb.log --port 27018 --bind_ip localhost --logappend --fork
· ./mongod --replSet test_replica_set --dbpath=/export/data/mongodb/replicaset2/data/ --logpath=/export/data/mongodb/replicaset2/logs/mongodb.log --port 27019 --bind_ip localhost --logappend --fork
· ./mongod --replSet test_replica_set --dbpath=/export/data/mongodb/replicaset3/data/ --logpath=/export/data/mongodb/replicaset3/logs/mongodb.log --port 27020 --bind_ip localhost --logappend --fork
注:三个副本集启动的结果除forked process不一致外,其余基本一致,不再展示
(5)连接到MongoDB:
·cd /export/servers/mongosh-2.3.3-linux-x64/bin
·./mongosh --host localhost --port 27018
(6)进行初始化:
· rs.initiate()
· rs.add("localhost:27019")
· rs.add("localhost:27020")
(7)关闭每个节点的MongoDB服务器:
•cd /export/servers/mongodb-linux-x86_64-rhel90-7.0.15/bin
•./mongod --shutdown --dbpath=/export/data/mongodb/replicaset1/data/ --port 27018
•./mongod --shutdown --dbpath=/export/data/mongodb/replicaset2/data/ --port 27019
•./mongod --shutdown --dbpath=/export/data/mongodb/replicaset3/data/ --port 27020
2.2 分布式部署
(1)三个节点上都需要安装启动mongod服务器,将hadoop1的mongod分发到hadoop2和hadoop3:
· scp -r /export/servers/mongodb-linux-x86_64-rhel90-7.0.15/ hadoop2:/export/servers/
· scp -r /export/servers/mongodb-linux-x86_64-rhel90-7.0.15/ hadoop3:/export/servers/
· scp -r /export/servers/mongosh-2.3.3-linux-x64/ hadoop2:/export/servers/
· scp -r /export/servers/mongosh-2.3.3-linux-x64/ hadoop3:/export/servers/
(2)创建存放MongoDB副本集数据的目录:
· mkdir -p /export/data/mongodb/replicaset/data
(3)创建存放MongoDB副本集日志的目录:
· mkdir -p /export/data/mongodb/replicaset/logs
(4)在MongoDB副本集日志的目录下创建日志文件:
· touch /export/data/mongodb/replicaset/logs/mongodb.log
(5)在三个虚拟机上以副本集的方法启动MongoDB
· cd /export/servers/mongodb-linux-x86_64-rhel90-7.0.15/bin
在Hadoop1上执行:./mongod --replSet test_replica_set --dbpath=/export/data/mongodb/replicaset/data/ --logpath=/export/data/mongodb/replicaset/logs/mongodb.log --port 27017 --bind_ip hadoop1 --logappend --fork
在Hadoop2上执行:./mongod --replSet test_replica_set --dbpath=/export/data/mongodb/replicaset/data/ --logpath=/export/data/mongodb/replicaset/logs/mongodb.log --port 27017 --bind_ip hadoop2 --logappend --fork
在Hadoop3上执行:./mongod --replSet test_replica_set --dbpath=/export/data/mongodb/replicaset/data/ --logpath=/export/data/mongodb/replicaset/logs/mongodb.log --port 27017 --bind_ip hadoop3 --logappend --fork
注:在Hadoop2和Hadoop3上启动副本集的结果与Hadoop1类似,不再展示
(6)进行初始化:rs.initiate({_id:"test_replica_set", members:[{_id :0,host:"hadoop1:27017"},{_id:1,host:"hadoop2:27017"}, {_id:2,host:"hadoop3:27017"]})
(7)测试是否同步:在Hadoop1上写入数据
•cd /export/servers/mongosh-2.3.3-linux-x64/bin
•./mongosh --host hadoop1 --port 27017
•>db.mycol.insertOne({item1: 'first item'})
(8)在Hadoop2上检查数据
•cd /export/servers/mongosh-2.3.3-linux-x64/bin
•./mongosh --host hadoop2 --port 27017
• > db.mycol.find()
可以发现Hadoop2与Hadoop1数据同步
(9)关闭每个节点的MongoDB服务器:
•cd /export/servers/mongodb-linux-x86_64-rhel90-7.0.15/bin
•./mongod -shutdown --dbpath=/export/data/mongodb/replicaset/data/ --port 27017
3.MongoDB集群的完整部署
(1)在hadoop1创建目录
存放分片集群的相关配置文件,数据和日志:mkdir -p /export/data/mongodb/sharedcluster/
存放相关配置文件:mkdir -p /export/data/mongodb/sharedcluster/configFile
存放config服务器的数据文件:mkdir -p /export/data/mongodb/sharedcluster/configserver_data
存放分片服务器shard1、shard2、shard3的数据文件:
· mkdir -p /export/data/mongodb/sharedcluster/shard1_data
· mkdir -p /export/data/mongodb/sharedcluster/shard2_data
· mkdir -p /export/data/mongodb/sharedcluster/shard3_data
存放日志文件,包括config服务器、分片服务器和mongos服务器:mkdir -p /export/data/mongodb/sharedcluster/logs
config服务器的日志文件:touch /export/data/mongodb/sharedcluster/logs/configserver.log
分片服务器shard1、shard2、shard3的日志文件:
· touch /export/data/mongodb/sharedcluster/logs/shard1.log
· touch /export/data/mongodb/sharedcluster/logs/shard2.log
· touch /export/data/mongodb/sharedcluster/logs/shard3.log
mongos服务器的日志文件:touch /export/data/mongodb/sharedcluster/logs/mongos.log
上述创建结果如下图所示:
(2)分发到hadoop2和hadoop3
· scp -r /export/data/mongodb/sharedcluster hadoop2:/export/data/mongodb/
· scp -r /export/data/mongodb/sharedcluster hadoop3:/export/data/mongodb/
注:hadoop3分发结果与Hadoop2类似,不再展示
(3)创建Hadoop1、Hadoop2、Hadoop3的shard1,shard2,shard3配置文件
· vi /export/data/mongodb/sharedcluster/configFile/shard1.conf
· vi /export/data/mongodb/sharedcluster/configFile/shard2.conf
· vi /export/data/mongodb/sharedcluster/configFile/shard3.conf
对于Hadoop1的shard2和shard3,分别修改对应的replSet为对应的shard2和shard3;对于Hadoop2和Hadoop3的除replSet的修改,还需要将bind_ip修改为对应的hadoop2和hadoop3
(4)分别在三台服务器上启动3个shard (共启动9个mongod服务器),执行
·cd /export/servers/mongodb-linux-x86_64-rhel90-7.0.15/bin
·./mongod -f /export/data/mongodb/sharedcluster/configFile/shard1.conf
·./mongod -f /export/data/mongodb/sharedcluster/configFile/shard2.conf
·./mongod -f /export/data/mongodb/sharedcluster/configFile/shard3.conf
注:Hadoop2和Hadoop3的启动类似于Hadoop1,不再展示
(5)部署shard:
在hadoop1登录:
·cd /export/servers/mongosh-2.3.3-linux-x64/bin
·./mongosh --host hadoop1 --port 27018
初始化副本集:
·rs.initiate()
·rs.add('hadoop2:27018')
·rs.add('hadoop3:27018')
查看副本集状态: > rs.status()
(6)在Hadoop2和Hadoop3上部署shard的步骤与Hadoop1类似,下面给出相关操作,执行结果不再给出
在hadoop2登录:
· cd /export/servers/mongosh-2.3.3-linux-x64/bin
· ./mongosh --host hadoop2 --port 27019
初始化副本集:
· rs.initiate()
· rs.add('hadoop3:27019')
· rs.add('hadoop1:27019')
查看副本集状态: > rs.status()
在hadoop3登录:
· cd /export/servers/mongosh-2.3.3-linux-x64/bin
· ./mongosh --host hadoop3 --port 27020
初始化副本集:
· rs.initiate()
· rs.add('hadoop1:27020')
· rs.add('hadoop2:27020')
查看副本集状态: > rs.status()
- 部署config server,创建hadoop1的config server配置文件:vi /export/data/mongodb/sharedcluster/configFile/configserver.conf
文件内容如下:
dbpath=/export/data/mongodb/sharedcluster/configserver_data
logpath=/export/data/mongodb/sharedcluster/logs/configserver.log
port=27022
bind_ip=hadoop1
logappend=true
fork=true
replSet=configs
#Config Server
configsvr=true
- hadoop2和hadoop3也分别创建configserver.conf文件,但需修改hadoop2,hadoop3中配置文件的bind_ip分别为hadoop2,hadoop3。
- 在三个节点中分别启动config server
· cd /export/servers/mongodb-linux-x86_64-rhel90-7.0.15/bin
· ./mongod -f /export/data/mongodb/sharedcluster/configFile/configserver.conf
注:三个节点启动结果基本一致,不再过多展示
(10)配置config server副本集,在hadoop1登录:
·cd /export/servers/mongosh-2.3.3-linux-x64/bin
·./mongosh --host hadoop1 --port 27022
(11)初始化副本集:
•rs.initiate()
•rs.add('hadoop2:27022')
•rs.add('hadoop3:27022')
(12)部署mongos:
在hadoop1上创建配置文件
·vi /export/data/mongodb/sharedcluster/configFile/mongos.conf
内容如下:
logpath=/export/data/mongodb/sharedcluster/logs/mongos.log
port=27021
bind_ip=hadoop1
logappend=true
fork=true
configdb=configs/hadoop1:27022,hadoop2:27022,hadoop3:27022
在hadoop2上创建配置文件
·vi /export/data/mongodb/sharedcluster/configFile/mongos.conf
内容将Hadoop1中的bind_ip修改为hadoop2
(12)分别在hadoop1和hadoop2上启动mongos
·cd /export/servers/mongodb-linux-x86_64-rhel90-7.0.15/bin
·./mongos -f /export/data/mongodb/sharedcluster/configFile/mongos.conf
(13)启动分片功能,在hadoop1登录mongos:
·cd /export/servers/mongosh-2.3.3-linux-x64/bin
·./mongosh --host hadoop1 --port 27021
(14)切换到数据库gateway
· mongos> use gateway
向分片集集群添加三个shard
· sh.addShard("shard1/hadoop1:27018,hadoop2:27018,hadoop3:27018")
· sh.addShard("shard2/hadoop1:27019,hadoop2:27019,hadoop3:27019")
· sh.addShard("shard3/hadoop1:27020,hadoop2:27020,hadoop3:27020")
(15)shard操作
· use admin
· db.runCommand({ listshards : 1} )
(16)mongos是无状态的节点,在hadoop1上直接kill掉:
· 找到进程号:ps aux | grep mongos
· kill -9 pid
(17)三个节点分别执行下面的命令来config server和三个副本集:
· /export/servers/mongodb-linux-x86_64-rhel90-7.0.15/bin/mongod --shutdown -f /export/data/mongodb/sharedcluster/configFile/configserver.conf
· /export/servers/mongodb-linux-x86_64-rhel90-7.0.15/bin/mongod --shutdown -f /export/data/mongodb/sharedcluster/configFile/shard1.conf
· /export/servers/mongodb-linux-x86_64-rhel90-7.0.15/bin/mongod --shutdown -f /export/data/mongodb/sharedcluster/configFile/shard2.conf
· /export/servers/mongodb-linux-x86_64-rhel90-7.0.15/bin/mongod --shutdown -f /export/data/mongodb/sharedcluster/configFile/shard3.conf
二.使用命令访问数据库
1.数据库:查看、使用和删除数据库
(1)查看当前数据库:db,即可返回当前数据库名称
(2)查看所有数据库:show database
(3)切换使用数据库(如果数据库不存在,则 MongoDB 会创建它):use mydb
(4)删除数据库:db.dropDatabase()
2.集合:查看、创建和删除集合
(1)创建集合(若集合不存在,MongoDB 会自动创建集合):
db.createCollection("user")
(2)查看当前数据库中的所有集合:show collections
(3)删除集合:db.user.drop()
3.文档:文档插入、文档查询、文档更新和文档删除
(1)插入文档:
db.users.insertMany([
{name: "Alice", age: 30, city: "New York"},
{name: "Bob", age: 25, city: "Los Angeles"},
{name: "Charlie", age: 35, city: "Chicago"},
{name: "David", age: 28, city: "New York"},
{name: "Eve", age: 22, city: "Los Angeles"}
])
(2)文档查询
①查询所有文档:db.users.find()
②查询符合条件的文档(查询age>25):db.users.find({age: {$gt: 25}})
③查询一个name为Alice的文档:db.users.findOne({name: "Alice"})
(3)文档更新
①更新单个文档,更新Alice的年龄为31
db.users.updateOne(
{name: "Alice"},
{$set: {age: 31}}
)
②更新多个文档,更新所有city为Los Angeles的为San Francisco
db.users.updateMany(
{city: "Los Angeles"},
{$set: {city: "San Francisco"}}
)
(4)删除文档
①删除单个文档,删除名为Eve的文档:db.users.deleteOne({name: "Eve"})
②删除多个文档,删除年龄为30的多个文档:db.users.deleteMany({age: {$lt: 30}})
4.聚合和管道:group,project,match,sort,limit和skip
(1)聚合
①使用 $match 来筛选出 age 大于 25 的用户:
db.users.aggregate([
{match: {age: {gt: 25}}}
])
②**$group**:按 city 分组并计算每个城市的用户数量:
db.users.aggregate([
{group: {_id: "city", totalUsers: {$sum: 1}}}
])
③$project:仅显示 name 和 age 字段:
db.users.aggregate([
{$project: {name: 1, age: 1, _id: 0}}
])
④ $sort:按 age 降序排列
db.users.aggregate([
{$sort: {age: -1}}
])
⑤$limit:限制返回前 3 条记录
db.users.aggregate([
{$limit: 1}
])
⑥ $skip:跳过前 1 条记录
db.users.aggregate([
{$skip: 1}
])
(2)组合:筛选年龄大于 25 的用户,按城市分组,并按用户总数降序排序,限制返回 3 条记录
db.users.aggregate([
{match: {age: {gt: 25}}},
{group: {_id: "city", totalUsers: {$sum: 1}}},
{$sort: {totalUsers: -1}},
{$limit: 3}
])
5.索引:索引的创建、查看和删除
(1)创建一个单字段索引(根据 name 字段):db.users.createIndex({name: 1})
(2)创建复合索引(根据 age 和 city 字段):db.users.createIndex({age: 1, city: 1})
(3)查看索引:db.users.getIndexes()
(4)根据索引名称删除:db.users.dropIndex("name_1")
(5)删除所有索引:db.users.dropIndexes()
三.数据库的设计
在MongoDB中,使用"集合"来存储数据,每个集合内包含多个"文档"。每个文档是一个类似JSON格式的数据结构,存储与实体相关的信息。图书管理系统包含三个主要实体:图书 、 读者 和借阅记录。它们之间通过一个关系来进行联系,借阅记录表示图书与读者之间的借阅关系,本系统共设计三个集合,分别是图集合(存储图书的相关信息)、读者集合(存储读者的基本信息)和借阅记录集合(存储借阅的记录)。
1.数据库设计
( 1 ) 图书 集合
集合名:Books
_id:唯一标识图书(相当于图书ID)。
title:图书名称。
category:图书类别(如文学、小说等)。
published_date:图书出版日期。
author:作者信息,包括作者名称和出生日期。
publisher:出版商信息,包括出版商名称和地址。
( 2 ) 读者 集合
读者名:Readers
_id:唯一标识读者(相当于读者ID)。
reader_name:读者的姓名。
dob:读者的出生日期。
contact:联系信息,包括电子邮件、电话和地址。
( 3 ) 借阅记录 集合
集合名:BorrowRecords
_id:唯一标识借阅记录(相当于借阅记录ID)。
book_id:借阅的图书ID,关联到Books集合中的_id。
borrow_date:借阅日期。
return_date:归还日期。
reader:读者信息,包括读者ID和读者姓名。
( 4 ) 实体和关系的增删改查
①新增操作
新增图书:通过插入新的文档到Books集合中。
新增借阅记录:通过插入新的文档到BorrowRecords集合中。
新增读者:通过插入新的文档到Readers集合中。
②删除操作
删除图书:通过_id删除Books集合中的文档。
删除借阅记录:通过_id删除BorrowRecords集合中的文档。
删除读者:通过_id删除Readers集合中的文档。
③更新操作
更新图书信息:通过_id在Books集合中更新相关字段(如书名、作者等)。
更新借阅记录:通过_id在BorrowRecords集合中更新借阅日期或归还日期。
更新读者信息:通过_id在Readers集合中更新读者姓名、联系方式等。
④查询操作
查询图书信息:通过_id查询Books集合中对应图书的信息。
查询借阅记录:通过book_id查询BorrowRecords集合中所有借阅该图书的记录。
查询读者借阅记录:通过reader_id查询BorrowRecords集合中该读者的借阅记录。
查询读者信息:通过_id查询Readers集合中该读者的详细信息。
2.集合设计与填充数据
(1)图书集合
{
"_id": "B001",
"title": "活着",
"category": "文学",
"published_date": "1993-06-01",
"author": {
"name": "余华",
"birth_date": "1960-04-03"
},
"publisher": {
"publisher_name": "作家出版社",
"publisher_address": "北京市朝阳区"
}
},
{
"_id": "B002",
"title": "百年孤独",
"category": "小说",
"published_date": "1967-06-05",
"author": {
"name": "加西亚·马尔克斯",
"birth_date": "1927-03-06"
},
"publisher": {
"publisher_name": "南海出版公司",
"publisher_address": "上海市徐汇区"
}
}
(2)读者集合
{
"_id": "R001",
"reader_name": "张三",
"dob": "1990-05-15",
"contact": {
"email": "zhsan@email.com",
"phone_number": "123-4567-8901",
"address": "北京市海淀区"
}
},
{
"_id": "R002",
"reader_name": "李四",
"dob": "2005-02-28",
"contact": {
"email": "lisi@email.com",
"phone_number": "987-6543-2100",
"address": "上海市浦东新区"
}
}
(3)借阅记录集合
{
"_id": "BR001",
"book_id": "B001",
"borrow_date": "2024-11-01",
"return_date": "2024-11-15",
"reader": {
"reader_id": "R001",
"reader_name": "张三"
}
},
{
"_id": "BR002",
"book_id": "B002",
"borrow_date": "2024-11-02",
"return_date": "2024-11-20",
"reader": {
"reader_id": "R002",
"reader_name": "李四"
}
}
四.编程实现数据库的访问
使用Python访问实现设计的图书管理系统的MongoDB 数据库,步骤如下:
(1)连接 MongoDB 数据库,创建LibraryDB数据库并创建图书集合、读者集合、借阅记录集合
from pymongo import MongoClient
client = MongoClient('mongodb:// hadoop1 :27017/')
# 选择数据库(如果没有数据库,MongoDB会自动创建)
db = client['LibraryDB']
books_collection = db['Books']
readers_collection = db['Readers']
borrow_records_collection = db['BorrowRecords']
(2)插入图书、读者和借阅记录文档
book_document = {
"_id": "B001",
"title": "活着",
"category": "文学",
"published_date": "1993-06-01",
"author": {
"name": "余华",
"birth_date": "1960-04-03"
},
"publisher": {
"publisher_name": "作家出版社",
"publisher_address": "北京市朝阳区"
}
}
# 插入单个文档
books_collection.insert_one(book_document)
# 插入多个文档
books_collection.insert_many([
{
"_id": "B002",
"title": "百年孤独",
"category": "小说",
"published_date": "1967-06-05",
"author": {
"name": "加西亚·马尔克斯",
"birth_date": "1927-03-06"
},
"publisher": {
"publisher_name": "南海出版公司",
"publisher_address": "上海市徐汇区"
}
}
])
reader_document = {
"_id": "R001",
"reader_name": "张三",
"dob": "1990-05-15",
"contact": {
"email": "zhsan@email.com",
"phone_number": "123-4567-8901",
"address": "北京市海淀区"
}
}
readers_collection.insert_one(reader_document)
borrow_record_document = {
"_id": "BR001",
"book_id": "B001",
"borrow_date": "2024-11-01",
"return_date": "2024-11-15",
"reader": {
"reader_id": "R001",
"reader_name": "张三"
}
}
borrow_records_collection.insert_one(borrow_record_document)
执行结果如下图所示:
(3)查询所有图书
# 查询Books集合中的所有文档
for book in books_collection.find():
print(book)
(4)查询某本图书的详细信息(按_id查找)
# 查询某本图书的详细信息
book_id = "B001"
book = books_collection.find_one({"_id": book_id})
print(book)
(5)查询某位读者的借阅记录
# 查询某位读者的借阅记录
reader_id = "R001"
borrow_records = borrow_records_collection.find({"reader.reader_id": reader_id})
for record in borrow_records:
print(record)
(6)更新图书信息(按_id更新)
# 更新图书的书名和类别
books_collection.update_one(
{"_id": "B001"},
{"$set": {"title": "活着(修订版)", "category": "现代文学"}}
)
(7)更新借阅记录的归还日期
# 更新借阅记录的归还日期
borrow_records_collection.update_one(
{"_id": "BR001"},
{"$set": {"return_date": "2024-11-18"}}
)
(8)删除某本图书(按_id删除)
# 删除图书
books_collection.delete_one({"_id": "B002"})