MongoDB的安装配置及使用(WIndows/Java)
创始人
2024-02-01 07:15:22

Hi,I‘m Shendi


下面主要介绍使用 Windows安装 MongoDB 和使用 Java 操作

文章目录

  • MongoDB
  • 下载
  • 创建数据目录
  • 运行
  • 配置
  • 安装服务
  • 创建用户
    • 用户角色列表
  • Java使用
    • 查询数据
    • 插入数据
    • 修改数据
    • 删除数据
    • 设置数据过期时间
  • 其他问题
    • MongoClient是否需要关闭?
    • 内存为什么只增不减?


MongoDB

MongoDB是一个基于分布式文件存储的数据库,由C++语言编写

MongoDB是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的,它支持的数据结构非常松散,是类型JSON的BSON格式,因此可以存储比较复杂的数据类型

特点是高性能、易部署、易使用,存储数据非常方便

NoSQL(NoSQL = Not Only SQL ),意即"不仅仅是SQL"



下载

https://www.mongodb.com/try/download/community

我windows系统,选择的zip格式,解压缩后即可使用,如果是选择的msi,则直接双击运行安装即可

结构如下
目录结构
可以先查阅README文件

其中 bin 目录下

  • mongod.exe(数据库服务器)
  • mongos.exe(分片)
  • Install-Compass.ps1(PowerShell脚本,执行后会安装Mongo的图形化工具)

执行Install-Compass.ps1后会安装MongoDBCompass,安装目录为 C:\Users\Administrator\AppData\Local

刚运行可能需要选择是否更改策略,输入 y 更改即可

将 bin 目录配置到环境变量,后面可直接使用 mongod 命令

Mongo 6.0后,bin目录下不再提供mongo.exe,如有需要可自行下载

https://www.mongodb.com/try/download/shell
我这里直接使用图形化工具 MongoDBCompass



创建数据目录

新建一个文件夹,一般命名为 data,用于存放数据库的数据



运行

使用 mongod --dbpath 来运行,其中dbpath为创建的数据目录

例如

mongod --dbpath C:/data

运行成功后结果大概如下,且命令行未结束

运行结果

接下来就可以连接上 MongoDB 了(可以使用mongo.exe),使用图形化工具 MongoDBCompass,打开后直接点击Connect就连接成功了,默认端口27017



配置

可以创建一个配置文件,这样后期方便维护管理

在mongodb文件夹下新建一个文件,格式为 YAML

yaml 不支持 tab 键,只允许空格

所有配置可参考

https://mongodb.net.cn/manual/reference/configuration-options/

# 系统日志
systemLog:destination: file# 日志的目录path: "log/mongod.log"# 重启后,日志是否追加到现有日志末尾,false则新建一个日志文件,旧日志文件以日期后缀命名logAppend: true
# 存储配置
storage:# 数据目录地址dbPath: "data"# 指定存储引擎,但是我的加上此行就无法启动了# engine: WiredTiger# 指定内存 1代表1G,最小0.25wiredTiger:engineConfig:cacheSizeGB: 0.25
# 网络配置
net:# 绑定的ip,默认localhost,多个使用逗号分隔bindIp: localhost,127.0.0.1# 绑定的端口,默认27017port: 27017

使用以下命令指定配置文件运行

mongod --config 配置文件地址
# 或
mongod -f 配置文件地址
# 例如
mongod --config C:/config.yml


安装服务

–install 参数安装服务

例如

mongod --config 配置文件地址 --install

使用 --config 指定配置文件地址,需要注意的是,指定的配置文件路径及文件内的一些路径需为绝对路径,例如

mongod --config "C:/config.yml" --install
systemLog:destination: filepath: "C:/Application/mongodb-win32-x86_64-windows-6.0.3/log/mongod.log"logAppend: true
storage:dbPath: "C:/Application/mongodb-win32-x86_64-windows-6.0.3/data"
net:bindIp: localhost,127.0.0.1port: 27017

命令

# 启动服务
net start MongoDB
# 关闭服务
net stop MongoDB
# 移除服务
mongod --remove

控制台需要为管理员权限,否则没有任何提示,在日志中可查看到

“msg”:“Error connecting to the Service Control Manager”,“attr”:{“error”:“拒绝访问。 (5)”}

服务和直接运行的方式使用一种即可

建议使用服务的方式运行,避免误操作关闭窗口导致MongoDB关闭



创建用户

MongoDB默认没有用户,且无需权限访问,如果在防火墙内不暴露出去则没有什么问题,否则需要进行以下配置

MongoDB 的用户是针对数据库而不是整个系统,所以所有数据库都需要设置

使用 MongoDB Compass 连接成功后,点击左下方 MONGOSH 即可输入命令

MONGOSH

有命令提示,通过 use 数据库 即可更换数据库

# 进入admin数据库
use admin
# 创建超级管理员用户 - 拥有所有数据库的所有权限
db.createUser({user:"admin",pwd:"adminpwd",roles:[{role:"root",db:"admin"}],# 可选, 自定义信息customData: {name : "Shendi"}
})

其中 user 代表账号,pwd代表密码,roles中为此用户的角色,可指定多个

在配置文件添加

# 安全配置
security:# 是否启用权限验证 enabled启用, disabled禁用authorization: enabled

最后,重启 MongoDB/服务

net stop mongodb
net start mongodb

图形化界面

重新打开,或 disconnect

在新建连接时点击 Advanced Connection Options 选择 Authentication -> Username/Password

填写username,password,因为是 root 角色,可以不填database,然后 Connect 即可

设置账号登录

命令行则使用

db.auth('账号','密码')

需要注意的是,同一个用户可以在多个地方同时登录,但有一个连接断开后,此用户的所有连接都失效

MongoDB Compass 和 Java 程序使用同一个用户,当 MongoDB Compass 断开连接后,导致 Java 报错


用户角色列表

  1. 数据库用户角色
    • read - 允许读取指定数据库的所有非系统集合,以及三个系统集合
      • system.indexes、system.js以及system.namesp
    • readWrite - 包含read的所有权限,以及修改所有非系统集合+system.js的数据
  2. 数据库管理角色
    • dbAdmin - 允许在指定数据库执行管理相关功能,例如查询统计信息,索引管理或访问 system.profile
    • dbOwner - 此角色为当前数据库的管理员,可以对数据库进行任何管理操作
    • userAdmin - 允许在指定数据库管理用户(增删改查),包括自己
  3. 集群管理角色 - 此类角色只能在 admin 数据库
    • clusterAdmin - 最高的集群访问权限,拥有其他集群管理角色的权限 + dropDatabase()权限
    • clusterManager - 对集群进行管理监控的权限
    • clusterMonitor - 对监控工具的只读访问权限
    • hostManager - 提供监控和管理服务器的权限
  4. 备份恢复角色
    • backup - 备份权限
    • restore - 还原权限
  5. 所有数据库角色 - 管理所有自定义数据库,不包含local和config数据库,此类角色只能在 admin 数据库
    • readAnyDatabase - 数据库读取的权限
    • readWriteAnyDatabase - 数据库读写的权限
    • userAdminAnyDatabase - 所有数据库的管理用户权限(userAdmin)
    • dbAdminAnyDatabase - 所有数据库的管理相关权限(dbAdmin)
  6. 超级用户角色
    • root - 所有权限
  7. 内部角色
    • __system - 仅用于 MongoDB 内部管理

其余用户操作

# 显示当前数据库所有用户
show users
# 更改密码
db.changeUserPassword("用户名","新密码")
# 修改用户 例 db.updateUser("admin", {customData : {name : "Shendi"}})
db.updateUser("用户名",{"要修改的数据":"值"});
# 删除用户
db.dropUser("用户名")


Java使用

下载 MongoDB Java驱动
https://mongodb.github.io/mongo-java-driver/


Maven导入

org.mongodbmongodb-driver-sync4.7.2

Gradle导入

dependencies {implementation 'org.mongodb:mongodb-driver-sync:4.7.2'
}

普通项目的话,除了要引入 mongodb-driver,还需要 bson 和 mongo-java-core 两个包

可以在maven仓库找到下载,或通过以下链接下载
https://download.csdn.net/download/qq_41806966/87079586


也可在文章最下方或在微信搜一搜sddxsck关注公众号后在公众号内发送 100000 获取

官方使用文档


数据库执行操作失败将抛出错误,所以一般需要使用 try catch 捕获



查询数据

下面是从官方复制的代码,大致意思是查找第一条指定数据库的指定collection下的包含指定key(title)+ 值(Back to the Future)的数据(Document)

import static com.mongodb.client.model.Filters.eq;
import org.bson.Document;
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;public static void main( String[] args ) {// Replace the uri string with your MongoDB deployment's connection string// String uri = "";String uri = "mongodb://localhost:27017";try (MongoClient mongoClient = MongoClients.create(uri)) {MongoDatabase database = mongoClient.getDatabase("sample_mflix");MongoCollection collection = database.getCollection("movies");Document doc = collection.find(eq("title", "Back to the Future")).first();System.out.println(doc.toJson());}
}

database为数据库,collection类似于表

如果有身份认证则 uri 与 MongoDB Compass 配置的 uri 一致即可

例如

// admin为用户名,adminpwd为密码, authSource为数据库,root角色可选
mongodb://admin:adminpwd@localhost:27017/?authMechanism=DEFAULT&authSource=admin

参数带有特殊字符则需要进行 url 编码

String account = URLEncoder.encode("admin", "UTF-8");
String pwd = URLEncoder.encode("adminpwd", "UTF-8");StringBuilder tmp = new StringBuilder();
tmp.append("mongodb://").append(account).append(":").append(pwd).append("@localhost:27017/?authMechanism=DEFAULT");String uri = tmp.toString();

其中 /?authMechanism=DEFAULT 这一部分去掉,否则执行出错 Unsupported authMechanism: DEFAULT

获取的 Document 对象操作方法与 JSONObject 类似

例如获取列表,数据结构如下

数据结构 - Shendi

代码及结果如下

代码+结果 - Shendi

其中 find() 查询所有数据可以使用游标 find().cursor() 或迭代器 find().iterator()

查询指定数量数据可以使用 find().limit(数量)

/** @author Shendi */
// cursor
MongoCursor cursor = collection.find().cursor();
while (cursor.hasNext()) {Document next = cursor.next();System.out.println(next.toJson());
}// iterator
MongoCursor it = collection.find().iterator();
while (it.hasNext()) {Document next = it.next();System.out.println(next.toJson());
}


插入数据

插入数据使用 MongoCollection 的 insertOne(插入单个) 或 insertMany(插入多个)

每一个 Document 对应一条数据,插入数据则先创建 Document,Document实例与JSONObject/Map对象使用方法类似,也有 parse 函数用来将 json 转换

Document d = Document.parse("{\"name\":\"Shendi\"}");
// 插入数据
collection.insertOne(d);d = new Document();
d.put("name", "Shendi");collection.insertOne(d);

执行后可以看到新增了两条数据

新增数据 - Shendi

也可以使用以下方法创建 Document

new Document().append("name", "Shendi").append("account", "admin");

insertMany函数则接收 List

List list = Arrays.asList(new Document().append("name", "Shendi"),new Document().append("name", "Shendi2"));
collection.insertMany(list);

insertOne 函数返回 InsertOneResult,insertMany 函数返回 InsertManyResult,可以用来获取刚插入数据的 id


例如

InsertOneResult one = collection.insertOne(d);
one.getInsertedId();InsertManyResult many = collection.insertMany(list);
many.getInsertedIds();


修改数据

使用 MongoCollection 的 updateOne()、updateMany() 或 replaceOne()

Document 实现了 Bson

Updates生成器(一个包含静态助手方法的工厂类)用来构造Document,当然,也可以直接使用Document,例如 new Document(“$set”,new Document(“num”,1))

// Updates 中, set-直接设置,addToSet-将值添加到数组中 键必须为数组,currentTimestamp-字段值设置为当前时间戳
// 构建更新文档
Bson updates = Updates.combine(updates.set("num", 1),Updates.addToSet("love", new Document().append("name", "MongoDB").append("scope", 2)),Updates.currentTimestamp("updateTime"));// 查找条件
Bson query = new Document().append("id", 1);/*成功执行后,函数返回UpdateResult的实例,如果在UpdateOptions实例中指定了upstart(true),则可以通过调用getModifiedCount()方法检索修改的文档数,或者通过调用getUpsertedId()方法获取_id字段的值。
*/
UpdateOptions options = new UpdateOptions().upsert(true);UpdateResult result = collection.updateOne(query, updates, options);
System.out.println(result.getModifiedCount());

数据结构如下

修改数据 - Shendi

运行后,结果如下

修改数据结果 - Shendi

updateMany(修改多个)使用方法与updateOne(修改单个)一致

replaceOne (替换单个)函数从文档中删除所有现有字段和值(_id除外),并替换为替换文档

例如,将上面所示数据结构进行以下操作

/*与 UpdateOptions 相似,但可直接使用getModifiedCount(), 如果在ReplaceOptions实例中设置了upstart(true),并且该操作导致插入新文档,则还可以通过调用getUpsertedId() 方法来检索文档的_id字段的值
*/
ReplaceOptions options = new ReplaceOptions().upsert(true);
// 参数1为条件,参数2为值
UpdateResult result = collection.replaceOne(new Document().append("id", 1),new Document().append("id", "2").append("name", "Shendi"),options);
System.out.println(result.getModifiedCount());

最终结果变为

替换数据结果 - Shendi



删除数据

使用 MongoCollection 的 deleteOne() 和 deleteMany()

判断条件使用 Filters 类,例如 Filters.eq(“id”, 2) 代表匹配 id=2 的数据,多个判断使用 Filters.and

这里将 id 为 2 的数据删除(上面替换时将 id 的值变为了字符串)

Bson query = Filters.eq("id", "2");
DeleteResult result = collection.deleteOne(query);
// 删除的数量
System.out.println(result.getDeletedCount());

deleteMany(删除所有匹配项) 使用方法同上



设置数据过期时间

给 Collection 设置字段 TTL(Time To Live) 索引,数据包含此字段的将会在指定时间后自动删除

在 MongoDB Compass 选择 Collection 后点击 Indexs,添加 TTL 索引

新建TTL索引 - Shendi

或通过命令行的方式

use Test
# test为collection名, expireAfterSeconds 为指定过期时间,单位秒
db.test.createIndex({ "字段名": 1 }, { expireAfterSeconds: 3 })

添加数据时,对应此索引字段需要传递 Date,例如

2022-11-19T03:41:57.153+00:00

在Java中,直接传递 java.util.Date 即可,例如

coll.insertOne(new Document().append("time", new Date()));

不包含TTL索引的字段或字段值非Date则不会过期删除



其他问题

MongoClient是否需要关闭?

经过测试,MongoClient 实例可以作为全局变量,而无需关闭

即使MongoDB服务器关闭,重启后,MongoClient 也可以正常使用,只会报几次错

测试代码如下

package shendi.test.mongodb;import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.List;
import java.util.concurrent.TimeUnit;import org.bson.Document;import com.mongodb.ConnectionString;
import com.mongodb.MongoClientSettings;
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;/*** 测试* 
* @author Shendi*/ public class TestMongoDB {static MongoClient mongoClient;public static void main(String[] args) throws UnsupportedEncodingException, Exception {// Replace the uri string with your MongoDB deployment's connection stringString account = URLEncoder.encode("admin", "UTF-8");String pwd = URLEncoder.encode("adminpwd", "UTF-8");StringBuilder tmp = new StringBuilder();tmp.append("mongodb://").append(account).append(":").append(pwd).append("@localhost:27017");String uri = tmp.toString();MongoClientSettings mcs = MongoClientSettings.builder().applyToSocketSettings(b -> {// 连接超时时间+读取超时时间, 默认30秒, 这里设置为三秒b.connectTimeout(3, TimeUnit.SECONDS).readTimeout(3, TimeUnit.SECONDS);}).applyToClusterSettings(b -> b.serverSelectionTimeout(3, TimeUnit.SECONDS)).applyConnectionString(new ConnectionString(uri)).build();mongoClient = MongoClients.create(mcs); // System.out.println(uri);MongoDatabase database = mongoClient.getDatabase("Test");MongoCollection collection = database.getCollection("test");while (true) {try {Document doc = collection.find().first();List loves = doc.getList("love", Document.class);for (Document love : loves) {System.out.println("爱好:" + love.getString("name") + ", 打分:" + love.getString("scope"));}Thread.sleep(3000);} catch (Exception e) {e.printStackTrace();}}}}


内存为什么只增不减?

新版默认使用 WiredTiger 存储引擎,经过测试,内存只增不减(删除数据甚至删库也不会减少)

默认占用内存:(电脑总内存-1) * 50%

例如 4G 默认占用 (4-1)*50% = 1.5G

而且测试时,增加1万数据,后删除1万数据,再增加1万数据,内存不会重复利用,等于占用了两万数据的内存

据说是将内存操作丢给操作系统处理,当其他应用内存不够时才会减少

可以通过以下配置指定最小内存,指定后虽然内存同样只增不减但可重复利用

# 指定内存 1代表1G,最小0.25wiredTiger:engineConfig:cacheSizeGB: 0.25

例如插入1w 数据占用100MB内存,删除后再插入 1W 数据仍然占用 100MB

插入10W数据占用 1GB,删除掉仍然占用 1GB,即使删库,数据超过 cacheSizeGB 指定的内存大小如果还有可用内存则会继续占用

相关内容

热门资讯

猫咪吃了塑料袋怎么办 猫咪误食... 你知道吗?塑料袋放久了会长猫哦!要说猫咪对塑料袋的喜爱程度完完全全可以媲美纸箱家里只要一有塑料袋的响...
埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...
脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...
demo什么意思 demo版本... 618快到了,各位的小金库大概也在准备开闸放水了吧。没有小金库的,也该向老婆撒娇卖萌服个软了,一切只...
世界上最漂亮的人 世界上最漂亮... 此前在某网上,选出了全球265万颜值姣好的女性。从这些数量庞大的女性群体中,人们投票选出了心目中最美...
埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...