mongodb入门篇
基本操作
登入与登出
#.登陆测试
/opt/mongodb/bin/mongosh -u dba_admin -p cf_rB1NKCzbaQuPH --authenticationDatabase admin --host 127.0.0.1 --port 3717 admin
//.查看版本
> db.version();
6.0.6
//.退出交互式界面
> quit
#.非交互式
/opt/mongodb/bin/mongosh -u dba_admin -p cf_rB1NKCzbaQuPH --authenticationDatabase admin --host 127.0.0.1 --port 3717 admin --quiet --eval "db.version()"
#.删除 db1库.aaa表
/opt/mongodb/bin/mongosh -u dba_admin -p cf_rB1NKCzbaQuPH --authenticationDatabase admin --host 127.0.0.1 --port 3717 admin --quiet --eval "db.getSiblingDB('db1').aaa.drop()"
/opt/mongodb/bin/mongosh -u dba_admin -p cf_rB1NKCzbaQuPH --authenticationDatabase admin --host 192.168.31.101 --port 3717 admin --quiet --eval "db.getSiblingDB('db1').getCollectionNames()"
实例的管理
- 根据 db.serverStatus() 可以查看服务器状态状态
//.可作为心跳检测
db.runCommand({ping:1})
//.查看版本
db.version();
//.查看 serverStatus() 所返回的大类
print(Object.keys(db.serverStatus()))
//.查看存储引擎
db.serverStatus().storageEngine.name;
//.查看连接数信息
db.serverStatus().connections;
//.查看详细指标
db.serverStatus().connections.current; //.当前连接数
db.serverStatus().connections.available; //.可用连接数
db.serverStatus().connections.totalCreated; //.历史总创建数
//.网络
db.serverStatus().network.bytesIn;
db.serverStatus().network.bytesOut;
//.操作计数器
db.serverStatus().opcounters.insert;
db.serverStatus().opcounters.query;
db.serverStatus().opcounters.update;
db.serverStatus().opcounters.delete;
db.serverStatus().opcounters.command;
//.缓存命中率: 1 - (wiredTiger.cache['pages read into cache'] / wiredTiger.cache['pages requested from the cache'])
//.低于 95% 可能意味着内存不足或工作集太大
db.serverStatus().wiredTiger.cache['pages read into cache'];
db.serverStatus().wiredTiger.cache['pages requested from the cache'];
//.查看启动参数
db.serverCmdLineOpts()
db.adminCommand({getCmdLineOpts:1})
//.检查是否企业版,是否启用认证,是否配置密码策略
var bi=db.adminCommand({buildInfo:1});
var gc=db.adminCommand({getCmdLineOpts:1});
var ee=!!bi.enterpriseModule;
var pa=gc.parsed.auth||(gc.parsed.security&&gc.parsed.security.authorization);
var pp=ee?!!db.getSiblingDB("admin").system.passwordPolicy.findOne():null;
print("enterprise:"+ee+",auth:"+pa+",password_policy:"+pp)
// 获取所有运行时参数
db.adminCommand({getParameter: '*'})
// 获取特定参数
db.adminCommand({getParameter: 1, "quiet": 1})
//.主机系统信息, 但不包括磁盘使用情况
db.hostInfo().system.memSizeMB // 总物理内存 (MB)
db.hostInfo().system.numCores // CPU核心数
db.hostInfo().system.cpuArch // CPU架构 (x86_64, arm64等)
db.hostInfo().system.numaEnabled // NUMA是否启用
db.hostInfo().os.name // 操作系统的发行版名称 (Ubuntu, CentOS, macOS)
db.hostInfo().os.version // 操作系统的内核/系统版本
//.查看内存指标
db.serverStatus().mem
db.serverStatus().mem.resident // 常驻内存大小 (MB),即实际使用的物理内存
//.mongo实际使用的物理内存、wiredTiger配置的内存、物理内存、mongo内存使用率、wiredTiger配置的内存占比率
var actual_use_mem_mb = db.serverStatus().mem.resident;
var total_system_mem_mb = db.hostInfo().system.memSizeMB;
var wiredTiger_config_size_mb = (db.serverStatus().wiredTiger.cache["maximum bytes configured"]/1024/1024).toFixed(0);
var mongo_mem_usage_percent = (actual_use_mem_mb / total_system_mem_mb * 100).toFixed(2);
var wiredTiger_mem_config_percent = (wiredTiger_config_size_mb / total_system_mem_mb * 100).toFixed(2);
print(actual_use_mem_mb + ',' + wiredTiger_config_size_mb + ',' + total_system_mem_mb + ',' + mongo_mem_usage_percent + ',' + wiredTiger_mem_config_percent)
//.提供操作系统级别的额外信息,主要用于诊断和监控Mongo与操作系统的交互
db.serverStatus().extra_info
//.测试方法1
echo 'printjson( db.version() );' > test1.sql
conn_str="--host 127.0.0.1 --port 3717"
command="db.runCommand({ping:1})"
mongosh $conn_str --quiet --file test1.sql
mongosh $conn_str --quiet --eval "show dbs;"
mongosh $conn_str --quiet --eval "JSON.stringify($command)"
//.测试方法2
echo 'db = connect( "localhost:3717/admin" );' > test2.js
echo 'printjson( db.version() );' >> test2.js
mongosh --file test2.js
数据库的管理
//.创建数据库,mongodb没有创建数据库的命令,通过use切换上下文并写入数据时,如果数据库不存在,则会自动创建
use db1;
db.createCollection("aaa");
//.查看数据库清单
show dbs;
show databases;
//.切换上下文数据库
use db1;
//.显示当前数据库名称
db;
db.getName();
//.查看所有数据库的大小
show dbs;
db.adminCommand({listDatabases:1}).databases.forEach(function(item){printjson(item)});
//.查看所有数据库的大小, 统一单位MB
const dbs = db.adminCommand({listDatabases:1}).databases;
dbs.forEach(d => { print(d.name + ', ' + (d.sizeOnDisk/1024/1024).toFixed(2) + ' MB'); });
//.查看所有数据库的大小
db.adminCommand({listDatabases:1}).databases.forEach(function(item){var db_name=item.name; var db_size=db.getSiblingDB(db_name).stats(1024*1024).storageSize; var db_st={name:db_name, storage_size:db_size}; printjson(db_st);});
//.拷贝数据库(mongodb 4.0 之后不再支持)
//.语法:db.copyDatabase(<fromdb>, <todb>, <fromhost>, <username>, <password>, <mechanism>);
//.示例:db.copyDatabase("db1","db2","192.168.31.101:3717","dba_admin","cf_rB1NKCzbaQuPH","MONGODB-CR")
//.示例:db.copyDatabase('db1','db1_bak');
//.删除当前数据库()
use db1;
db;
db.dropDatabase();
数据表的管理
//.切换上下文数据库
use db1;
//.创建数据表-显示创建
db.createCollection("aaa");
//.创建数据表-隐示创建
db.aaa.insert({"name":"sam"});
//.创建数据表(capped为true指定自动覆盖、size指定最大字节数、max指定最大行数为3,测试写入5行,查看只有第3-5行)
db.createCollection("bbb", {capped: true, size: 65536, max: 3});
for(var i=1;i<=5;i++){db.bbb.insert({"username":"user"+i,"created_at":new Date()});};
db.bbb.find();
//.查看当前db的数据表清单
show tables;
show collections;
db.getCollectionNames();
//.查看当前db的表数量及库大小
db.stats();
db.stats(1024); //.以KB为单位的库大小, 注意 dataSize 代表实际存储的数据总大小(未压缩)
db.stats(1048576); //.以MB为单位的库大小, 注意 storageSize 代表在磁盘上实际占用的空间大小
db.stats(1073741824); //.以GB为单位的库大小
//.查看当前库所有表的行数及大小
db.getCollectionNames().forEach(c => {
const stats = db[c].stats();
print(`${c}: 行数=${(stats.count)}, 数据=${(stats.size/1024/1024).toFixed(2)}MB, 存储=${(stats.storageSize/1024/1024).toFixed(2)}MB, 碎片率=${(stats.storageSize/stats.size).toFixed(2)}`);
});
//.获取所有数据库的表的大小(排除系统数据库), 返回格式: 库名,表名,行数,数据大小(单位MB),存储大小(单位MB),碎片率
var dbs = db.adminCommand('listDatabases').databases;
dbs.forEach(dbInfo => {
var dbName = dbInfo.name;
if (dbName === 'admin' || dbName === 'local' || dbName === 'config') { return; }
var targetDb = db.getSiblingDB(dbName);
var collections = targetDb.getCollectionNames();
collections.forEach(collection => {
const stats = targetDb[collection].stats();
print(`库名=${dbName},表名=${collection},行数=${stats.count},数据大小=${(stats.size/1024/1024).toFixed(2)},存储大小=${(stats.storageSize/1024/1024).toFixed(2)},碎片率=${(stats.storageSize/stats.size).toFixed(2)}`);
});
});
//.查看表名与文件名的对应关系(uri对应的就是该表对应的文件名)
db.aaa.stats();
//.查看指定表的行数及大小
db.aaa.count(); // 查看行数
(db.aaa.dataSize()/1024/1024).toFixed(2) // 仅查看数据大小,单位MB
(db.aaa.totalIndexSize()/1024/1024).toFixed(2) // 仅查看索引大小,单位MB
(db.aaa.totalSize()/1024/1024).toFixed(2) // 查看存储大小(数据+索引,压缩后)
(db.aaa.storageSize()/1024/1024).toFixed(2) // 查看磁盘上实际占用的空间(含索引)
//.查看指定表的行数及大小及膨胀率
var stats = db.aaa.stats();
var ratio = stats.storageSize / stats.size;
print("行数: " + stats.count + " | 存储: " + (stats.storageSize/1024/1024).toFixed(2) + "MB | 数据: " + (stats.size/1024/1024).toFixed(2) + "MB | 索引: " + (stats.totalIndexSize/1024/1024).toFixed(2) + "MB | 膨胀率: " + ratio.toFixed(2));
//.备份数据表(mongodb 5.0 之后不再支持)
// db.aaa.copyTo("aaa_bak");
//.备份数据表(新表会自动创建)
db.aaa.find().forEach(function(x){db.aaa_bak.insert(x)});
//.把源库db1中的aaa表复制到目标库db2的bbb表中
use db1;
db.aaa.find().forEach(function(x){db.getSiblingDB('db2')['bbb'].insert(x);});
//.把aaa表中 < 20240901 的数据复制到bbb表中
//.对于大数据量 $out 比 insertMany 效率高很多,原子操作(要么全部成功要么全部失败),完全替换而非追加,目的表不会继承索引
use db1;
db.aaa.deleteMany({});
db.aaa.insertMany([{entry:"test_2023",InsertTime: new Date("2023-07-01T11:20:00"),content:"要删除"}, {entry:"test_2024",InsertTime: new Date("2024-09-02T08:00:00"),content:"要保留"}]);
var cutoffDate = new Date("2024-09-01T00:00:00");
db.aaa.aggregate([ {$match:{InsertTime:{$lt:cutoffDate}}}, {$out:"bbb"} ]);
//.修改表名-方式1
use db1;
db.aaa.renameCollection("bbb");
//.修改表名-方式2(使用renameCollection会迁移数据+索引)
use admin;
db.runCommand({'renameCollection':'db1.bbb','to':'db1.aaa'});
//.清空全表
db.aaa.deleteMany({});
//.删除数据表
db.aaa.drop();
db.getCollection("tmpCJWjw.renameCollection").drop();
//.如果表名为数字或以数字开头,则操作表的时候需要在表名前后添加引号,不可以用 db.表名.countDocuments(); 的方式
db.createCollection("10001");
db.getCollection("10001").insert({"name":"sam"});
db.getCollection('10001').find();
增删改查
- 修改数据的话,请注意 save / update / replace 之间的区别
insert 与 save
- mongodb 5.0 之后不再支持 db.collection.save,请替换使用 insertOne、insertMany、bulkWrite
//.切换上下文数据库
use db1;
//.写入数据-显示写入(建表+写入)
db.createCollection("aaa");
db.getCollection("aaa").insert({"name":"sam"});
//.写入数据-隐示写入(建表+写入)
db.aaa.insert({"name":"sam"});
//.插入单条数据
db.aaa.insertOne({name:'sam',qty:100});
//.插入多条数据
db.aaa.insertMany([{name:'joy',qty:25},{name:'joy',qty:25}]);
//.早期版本save会自动建表(mongodb 5.0 之后不再支持)
// db.aaa.save({"id":110,"name":"tom"});
//.批量写操作
db.aaa.bulkWrite( [
{ insertOne: { document: { name: "tom", age: 6 } } },
{ insertOne: { document: { name: "sam", age: 10 } } },
{ updateOne: { filter: { name: "joy" }, update: { $set: { age: 8 } } } },
{ deleteOne: { filter: { name: "poy"} } }
] );
//.批量写入(示例批量写入1w行)
for(var i=1;i<=10000;i++){db.aaa.insert({"username":"user"+i,"created_at":new Date()});};
db.aaa.count();
find
//.切换上下文数据库
use db1;
//.查看表的行数
db.aaa.count();
db.aaa.countDocuments();
db.aaa.countDocuments({"name":"sam"});
//.限制返回的行数(示例只返回10行)
db.aaa.find().limit(10);
db.aaa.find({"name":"sam"}).limit(10);
//.返回第一条满足条件的数据,等价于 db.aaa.find().pretty().limit(1)
db.aaa.findOne();
db.aaa.find().pretty().limit(1)
//.返回3条记录并打印信息
db.aaa.drop();
db.aaa.insertMany([{name:"tom",city:"shanghai",age:18},{name:"joy",city:"beijing",age:25}]);
db.aaa.find().limit(3).forEach(function(aaa) {print(aaa.name + ' age is ' + aaa.age)});
//.特定字段返回(_id字段总是会被返回)
db.aaa.drop();
db.aaa.insertMany([{name:"tom",city:"shanghai",age:18},{name:"joy",city:"beijing",age:25}]);
db.aaa.find({}, {name:1});
db.aaa.find({}, {name:true});
db.aaa.find({city:"shanghai",name:"tom"}, {name:1, age:1});
//.排除特定字段返回(将字段设置为0则不再显示)
db.aaa.find({}, {age:0});
db.aaa.find({}, {age:false});
db.aaa.find({city:"shanghai",name:"tom"}, {_id:0, age:0});
//.使用sort排序
db.aaa.drop();
db.aaa.insertMany([{name:"tom",city:"shanghai",age:18},{name:"joy",city:"beijing",age:25}]);
db.aaa.find({}, {name:1,age:1}).sort({age: 1}); //.升序
db.aaa.find({}, {name:1,age:1}).sort({age: -1}); //.降序
//.查询 age > 19 and age < 39 的数据
db.aaa.find({age:{$gt:19, $lt:39}});
//.查询 name <> "kugo" and age >= 20 的数据
db.aaa.find({name: {$ne: "kugo"}, age: {$gte: 20}});
//.查询 age in (19,29) 的数据
db.aaa.find({age: {$in: [19,25]}});
//.查询 age取模10等于0 的数据
db.aaa.drop();
db.aaa.insertMany([{name:"tom",city:"shanghai",age:18},{name:"joy",city:"beijing",age:20}]);
db.aaa.find({age:{$mod:[10,0]}});
//.查询 city like %jing% 的数据
db.aaa.find({city:{$regex:"jing"}}).limit(20);
//.查询 city <> bei% 的数据
db.aaa.find({city: {$not: /^bei.*/}});
//.查询9-39岁、city为shanghai的name,age字段
db.aaa.find({age:{$gt:9, $lt:39},city:"shanghai"}, {_id:0, name:1,age:1}).limit(10);
//.查找name为tom或sam,age大于20、小于50的数据
db.aaa.drop();
db.aaa.insertMany([{name:'tom',age:18},{name:'tom',age:25},{name:'sam',age:30}]);
db.aaa.find({'$or':[{"name":'tom'},{"name":'sam'}],"age":{'$gt':20,'$lt':80}});
//.指定列去重
db.aaa.drop();
db.aaa.insertMany([{name:'tom',qty:18},{name:'tom',qty:25},{name:'joy',qty:30}]);
db.aaa.distinct("name");
update 与 replace
//.切换上下文数据库
use db1;
//.仅更新第一条满足条件的数据
db.aaa.updateOne({"name":"joy"},{$set:{"qty":100}});
//.更新符合条件的所有数据
db.aaa.updateMany({"name":"joy"},{$set:{"qty":200}});
//.字段改名,示例:将name为tom的age字段重命名为age2
db.aaa.drop();
db.aaa.insertMany([{"name":"tom",age:18},{"name":"joy",age:25}]);
db.aaa.updateMany({name:"tom"},{$rename:{"age":"age2"}});
//.删除字段,示例:将name为tom的年龄字段删除
db.aaa.drop();
db.aaa.insertMany([{"name":"tom",age:18},{"name":"joy",age:25}]);
db.aaa.updateMany({name:"tom"},{$unset:{age:1}});
//.数字字段增加value,示例:将name为tom的age增加10
db.aaa.drop();
db.aaa.insertMany([{"name":"tom",age:18},{"name":"joy",age:25}]);
db.aaa.updateMany({name:"tom"},{$inc:{age:10}});
//.洗数据 - 将满足条件的数据(name为joy)字段b更新为字段a的内容
db.aaa.drop();
db.aaa.insertMany([{"name":"tom",age:18,qty:10},{"name":"joy",age:25,qty:11}]);
db.aaa.find().forEach(function(item){db.aaa.updateMany({"name":"joy"},{"$set":{"qty":item.age}})});
//.替换第一条满足条件的数据,可替换除 _id 之外的所有内容
db.aaa.replaceOne({name:"joy"}, {name:"joy",age:31});
//.模糊更新,将 testbank-file.oss-cn-shanghai.aliyuncs.com 替换为 testbank-file01.oss-cn-shanghai.aliyuncs.com
db.aaa.find({con:{$regex:"testbank-file.oss-cn-shanghai.aliyuncs.com"}}).count(); //.确认一下受影响的行数
db.aaa.find().forEach(function(x){db.aaa_20210202_bak.insert(x)}); //.备份一下受影响的数据
db.aaa.find({'con':{'$regex': "testbank-file.oss-cn-shanghai.aliyuncs.com"}}).forEach(
function(item) {
var tmp = String(item.con)
tmp = tmp.replace('testbank-file.oss-cn-shanghai.aliyuncs.com','testbank-file01.oss-cn-shanghai.aliyuncs.com')
if (tmp == null){
print(item.con)
}
item.con = tmp;
db.aaa.save(item);
}
);
delete 与 remove
//.切换上下文数据库
use db1;
//.删除符合条件的所有数据(后续版本会废弃)
db.aaa.find({"name":"sam"}).count();
db.aaa.remove({"name":"sam"});
//.仅删除第一条符合条件的数据
db.aaa.deleteOne({name:'sam'});
//.删除符合条件的所有数据,比如name为joy
db.aaa.drop();
db.aaa.insertMany([{"name":"tom",age:18},{"name":"joy",age:25}]);
db.aaa.deleteMany({"name":"joy"});
//.删除符合条件的所有数据,比如某个时间区间
db.aaa.drop();
db.aaa.insertMany([{"name":"tom","created_at":"2020-12-24T12:08:11.063Z"}]);
db.aaa.insertMany([{"name":"joy","created_at":"2022-12-24T12:08:11.063Z"}]);
db.aaa.remove({"created_at":{$gte:"2018-07-01",$lte:"2021-08-01"}});
db.aaa.remove({"created_at":{$regex:".*2022-12.*"}});
//.清空表
db.aaa.remove({});
db.aaa.deleteMany({});
角色的管理
createRole
- 创建自定义角色(示例
healthChecker,用于mongodb巡检的最小权限)
//.创建自定义角色(示例 healthChecker,用于mongodb巡检的最小权限)
db.createRole({
role: "healthChecker",
privileges: [
{
resource: { cluster: true },
actions: [
"serverStatus", // 服务器状态
"top", // 操作统计
"connPoolStats", // 连接池统计
"getCmdLineOpts", // 启动参数
"hostInfo", // 主机信息
"inprog", // 当前操作
"listDatabases", // 数据库列表
"replSetGetStatus", // 副本集状态
"replSetGetConfig", // 副本集配置
"getParameter", // 参数获取
"getShardMap", // 分片映射
"listShards", // 分片列表
]
},
{
resource: { db: "", collection: "" },
actions: [
"collStats", // 集合统计
"dbStats", // 数据库统计
"indexStats", // 索引统计
"listCollections", // 集合列表
"listIndexes" // 索引列表
]
}
],
roles: []
});
//.基于自定义角色(示例 healthChecker)创建账号(示例 test01)
db.createUser({
user: "test01",
pwd: "Admin_147",
roles: ["healthChecker"]
});
//.基于默认角色(示例 readAnyDatabase)创建账号(示例 test02)
db.createUser({user:"test02",pwd:"Admin_147",roles:[{role:"readAnyDatabase", db:"admin"}]});
//.查看所有自定义的角色信息
db.getRoles()
//.查看所有的角色信息
db.runCommand({rolesInfo:1,showBuiltinRoles:true})
db.runCommand({rolesInfo:1,showBuiltinRoles:true}).roles.forEach(r => print(r.role))
grantPrivilegesToRole
- 针对已经创建的角色,可以通过 grantPrivilegesToRole 为用户定义的角色分配特权
//.创建自定义角色,resource 针对 cluster
db.createRole({role:"healthChecker",privileges:[{resource:{cluster:true},actions:["serverStatus","top"]}],roles:[]});
//.针对自定义角色,添加新的角色,resource 针对 db
db.grantPrivilegesToRole("healthChecker",[{resource:{db:"",collection:""},actions:["dbStats","listIndexes"]}]);
- 利用 showPrivileges 查看账号的角色信息
db.runCommand({usersInfo:"dba_check",showPrivileges:true});
db.getUser("dba_check")
dropRole
//.删除角色
db.dropRole("healthChecker");
账号的管理
createUser
//.示例1:创建超级管理员账号(超级权限,只能在admin数据库中可用)
use admin;
db.createUser({user:'rwuser',pwd:'rIFz_1Se4B7pBK6Z',roles:['root']},{w:'majority',wtimeout:5000});
db.createUser({user:'dba_admin',pwd:'cf_rB1NKCzbaQuPH',roles:[{role:'root',db:'admin'}]});
show users;
//.示例2:创建备份帐号
use admin;
db.createUser({user:"dba_backup",pwd:"Admin_369",roles:[{"role":"backup","db":"admin"}]});
//.示例3:创建全局读写账号(全局角色,只能在admin数据库中可用)
use admin;
db.createUser({user:"dba_admin_rw",pwd:"Admin_147",roles:[{"role":"readWriteAnyDatabase","db":"admin"}]});
//.示例4:创建全局只读账号(全局角色,只能在admin数据库中可用)
use admin;
db.createUser({user:"dba_admin_r",pwd:"Admin_258",roles:[{role:"readAnyDatabase", db:"admin"}]});
//.示例5:创建业务读写账号
use bigdata;
db.createUser({user:"user_bigdata_push",pwd:"dw_RX2a_6GemCf7u",roles:[{"role":"readWrite","db":"bigdata"}],passwordDigestor:"server"});
//.示例6:创建业务只读账号
use bigdata;
db.createUser({user:"user_bigdata_readonly",pwd:"dw_iuDIfQzWgVb9G",roles:[{"role":"read","db":"bigdata"}],passwordDigestor:"server"});
修改账号
//.修改密码
use bigdata;
db.changeUserPassword("user_bigdata_readonly","Aa_123456");
db.updateUser("user_bigdata_readonly",{pwd:"Aa_123456"});
//.修改权限-通过grant与revoke
use bigdata;
db.grantRolesToUser("user_bigdata_readonly",[{role:"readWrite",db:"db1"},{role:"read",db:"db2"}]);
db.revokeRolesFromUser("user_bigdata_readonly",[{role:"read",db:"db2"}]);
//.修改权限-通过updateUser
use bigdata;
db.updateUser("user_bigdata_readonly",{roles:[{role:"readWrite",db:"db1"}, {role:"readWrite",db:"db2"}]});
db.updateUser("user_bigdata_readonly",{roles:[{role:"read",db:"db1"}]});
//.切换账号(注:先在认证库下面db.auth(),然后再use切换上下文)
use admin;
db.auth("dba_admin_r","Admin_258");
use db1;
show tables;
//.查看全局账号
use admin;
db.system.users.find();
db.system.users.find({}, {name:1}); //.仅显示name
db.system.users.find({'db':'admin'}); //.根据db查用户
db.system.users.find({'user':'dba_admin'}); //.根据name查用户
//.查看当前库下的账号
use db1;
show users;
dropUser
//.删除用户
use bigdata;
db.dropUser("user_bigdata_push");
show users;
//.删除用户
use admin;
db.system.users.remove({user:"user_bigdata_readonly"});
show users;
cd /d d:\sqldata\mongodb\bin
.\mongo.exe --authenticationDatabase admin -u dba_admin -p cf_rB1NKCzbaQuPH
cd /d d:\sqldata\mongodb\bin
.\mongostat.exe -uroot --authenticationDatabase=admin -u dba_admin -p cf_rB1NKCzbaQuPH
| 角色名称 |
角色类型 |
角色权限 |
危险等级 |
| read |
数据库用户角色 |
允许用户读取指定数据库 |
- |
| readWrite |
数据库用户角色 |
允许用户读写指定数据库 |
- |
| dbAdmin |
数据库管理角色 |
允许用户在指定数据库中执行管理函数,如索引创建、查看统计等 |
- |
| userAdmin |
数据库管理角色 |
允许用户向system.users集合写入,可以找指定数据库里创建、删除和管理用户 |
- |
| dbOwner |
数据库管理角色 |
允许在当前DB中执行任意操作 |
极高 |
| backup |
备份恢复角色 |
- |
中 |
| restore |
备份恢复角色 |
- |
高 |
| readAnyDatabase |
所有数据库角色 |
赋予用户所有数据库的读权限,只在admin数据库中可用 |
- |
| readWriteAnyDatabase |
所有数据库角色 |
赋予用户所有数据库的读写权限,只在admin数据库中可用 |
- |
| userAdminAnyDatabase |
所有数据库角色 |
赋予用户所有数据库管理User的权限,只在admin数据库中可用 |
高 |
| dbAdminAnyDatabase |
所有数据库角色 |
赋予管理所有数据库的权限,只在admin数据库中可用 |
高 |
| root |
超级账号 |
超级权限,只在admin数据库中可用 |
极高 |
| clusterAdmin |
集群管理角色 |
赋予管理集群的最高权限,只在admin数据库中可用 |
极高 |
| clusterManager |
集群管理角色 |
赋予管理和监控集群的权限 |
- |
| clusterMonitor |
集群管理角色 |
赋予监控集群的权限,对监控工具具有readonly的权限 |
- |
| hostManager |
集群管理角色 |
赋予管理Server |
- |
// 必须切换到 admin 库查看
use admin;
db.system.users.find({"roles.role":{$in:["root","dbOwner","clusterAdmin"]}}).pretty()
db.system.users.find({"roles.role":{$in:["root","dbOwner","clusterAdmin"]}},{_id:1,roles:1}).pretty()
// 必须切换到 admin 库查看
db.system.users.find(
{"roles.role": {$in: ["root","dbOwner","clusterAdmin","userAdminAnyDatabase","dbAdminAnyDatabase"]}}
).forEach(function(user) {
var highrole = [];
user.roles.forEach(function(role) {
if (["root","dbOwner","clusterAdmin","userAdminAnyDatabase","dbAdminAnyDatabase"].includes(role.role)) {
highrole.push(role.role + "," + role.db);
}
});
if (highrole.length > 0) {
print(user.user + "," + user.db + "," + highrole.join(", "));
}
});
// 可以在任意库查看
var users = db.getSiblingDB("admin").runCommand({usersInfo:1});
if (users && users.ok === 1 && users.users) {
var highPrivUsers = users.users.filter(function(user) {
return (user.roles || []).some(function(role) {
return ["root","dbOwner","clusterAdmin","userAdminAnyDatabase","dbAdminAnyDatabase"].includes(role.role) ||
(role.db === "admin" && ["root","dbOwner","clusterAdmin","userAdminAnyDatabase","dbAdminAnyDatabase"].includes(role.role));
});
});
highPrivUsers.forEach(function(user) {
var roleInfo = (user.roles || []).map(function(role) { return role.role + "," + (role.db || "admin"); }).join("; ");
print(user.user + "," + user.db + "," + roleInfo);
});
};
connections
//.查看当前DB的连接的主机地址
db.getMongo()
#.输出所有连接
echo "db.currentOp(true).inprog;" | /opt/mongodb/bin/mongosh -u dba_admin -p cf_rB1NKCzbaQuPH --authenticationDatabase admin --host 127.0.0.1 --port 3717 admin | grep "client:"
//.查看总的连接数
db.serverStatus().connections;
//.查看当前所有的连接详情
db.currentOp();
db.currentOp(true).inprog;
//.杀掉某个具体的进程
db.killOp(<number>);
索引与调优
索引的创建与删除
//.准备测试数据
use db1;
db.aaa.drop();
db.aaa.insertMany([{name:'sam',qty:25,insert_time:new Date()},{name:'joy',qty:40,insert_time:new Date()}]);
db.aaa.find();
//.查看索引
db.aaa.getIndexes();
//.根据查询条件查看执行计划
db.aaa.find({name:"sam"}).explain();
//.创建索引
//.实测: 一张大表26337252行、dataSize共122G、totalSize共148G,针对时间字段添加索引耗时 1133 秒
db.aaa.ensureIndex({"name":1}, {"background":true}); //.单列索引,1为升序,-1为降序,后台执行
db.aaa.ensureIndex({"qty":-1}, {"unique":true}); //.唯一索引
db.aaa.ensureIndex({"name":1, "qty":-1}); //.组合索引
db.aaa.ensureIndex({"name":-1}, {"name":"aaa_id","background":true});
//.唯一索引也支持组合索引
db.members.createIndex({lastname:1, firstname:1}, {unique:true})
//.创建嵌入式的索引
db.aaa.drop();
db.aaa.insertOne({name:"sam", location:{state:"NY", city:"New York"}, "age":18});
db.aaa.find({"location.state":"NY"});
db.city.ensureIndex({"location.state":1});
//.时效性数据推荐使用TTL(Time to Live)索引,对一个date类型的单列配置过期属性(时间戳或clock则不行)可实现对文档的自动过期删除
db.aaa.createIndex({"insert_time":1}, {expireAfterSeconds:60*60*24*7});
//.使用 collMod 修改 expireAfterSeconds 属性
db.runCommand({collMod: "aaa", index: { keyPattern: { insert_time: 1 }, expireAfterSeconds: 60}});
//.重建索引,该操作会删除表上的所有索引(包含_id)并重建所有索引
db.aaa.reIndex();
//.根据name删除指定索引
db.aaa.dropIndex("name_1");
//.当前库所有表的索引个数
db.getCollectionNames().forEach(tabs => print(tabs + "," + db[tabs].getIndexes().length))
//.所有库所有表的索引个数
var dbs = db.adminCommand('listDatabases').databases;
dbs.forEach(dbInfo => {
var dbName = dbInfo.name;
if (dbName === 'admin' || dbName === 'local' || dbName === 'config') { return; }
var targetDb = db.getSiblingDB(dbName);
var collections = targetDb.getCollectionNames();
collections.forEach(collection => {
const stats = targetDb[collection].getIndexes();
if (stats.length >= 1) {
print(`${dbName},${collection},${stats.length}`);
}
});
});
//.删除所有索引
db.aaa.dropIndexes();
压缩库表
//.使用compact压缩单个集合或索引(注:compact操作是不会释放磁盘空间的,而是把释放的空间继续给mongodb使用)
use db1;
db.aaa.storageSize(); //.记录一下压缩前的大小
db.aaa.runCommand('compact'); //.压缩方式1
db.runCommand({compact : 'aaa' }); //.压缩方式2
db.aaa.storageSize(); //.记录一下压缩后的大小
附录
兼容性更改
| 已删除的命令 |
受影响的版本 |
替代方案 |
| db.collection.save() |
MongoDB 5.0 |
db.collection.insertOne() db.collection.insertMany() |
| db.collection.copyTo() |
MongoDB 5.0 |
$out |
| db.collection.ensureIndex() |
MongoDB 5.0 |
db.collection.createIndex() |
| db.copyDatabase('db1','db1_bak') |
MongoDB 4.0 |
- |
| db.collection.count() |
MongoDB 5.0 |
- |
| db.collection.update() |
- |
- |