Mongodb基础 学习小结
MongoDB是一个基于分布式文件存储的数据库。由C++语言编写。旨在为WEB应用提供可扩展
的高性能数据存储解决方案。
MongoDB是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰
富,最像关系数据库的。它支持的数据结构非常松散,是类似json的bson格式,因此可以
存储比较复杂的数据类型。
Mongo最大的特点是它支持的查询语言非常强大,其语法有点类似于面向对象的查询语言,
几乎可以实现类似关系数据库单表查询的绝大部分功能,而且还支持对数据建立索引。
MongoDB主要场景如下:
1)网站实时数据处理。非常适合实时的插入、更新与查询,并具备网站实时数据存储所需的复制及高度伸缩性。
2)缓存。由于性能很高,它适合作为信息基础设施的缓存层。在系统重启之后,由它搭建的持久化缓存层可以避免下层的数据源过载。
3)高伸缩性的场景。非常适合由数十或数百台服务器组成的数据库,它的路线图中已经包含对MapReduce引擎的内置支持。
不适用的场景如下:
1)要求高度事务性的系统。
2)传统的商业智能应用。
3)复杂的跨文档(表)级联查询。
/*********** Windows版
Windows 安装 msi 包
下载:https://www.mongodb.com/download-center#community
选择 Community Server 选择一个稳定版
安装...
然后找个合适位置 建立目录,用于存放数据和日志:
md "\data\db" "\data\log"
测试启动:(必须指定db路径) */
"C:\Program Files\MongoDB\Server\3.6\bin\mongod.exe" --dbpath="c:\data\db"
/*将 MongoDB 安装为 Windows 服务:
创建配置文件:C:\Program Files\MongoDB\Server\3.6\mongod.cfg
内容如下:(指定了log和db的位置) */
systemLog:
destination: "file"
path: "c:\\data\\log\\mongod.log"
storage:
dbPath: "c:\\data\\db"
// 安装服务:
sc.exe create MongoDB binPath= "\"C:\Program Files\MongoDB\Server\3.6\bin\mongod.exe\" --service --config=\"C:\Program Files\MongoDB\Server\3.6\mongod.cfg\"" DisplayName= "MongoDB" start= auto
// 如果成功则显示:CreateService SUCCESS
// 以后就可以系统服务中管理了。
// 卸载服务:(需要先停止服务)
sc.exe delete MongoDB
/**
管理工具 Robomongo :
下载:https://robomongo.org/download
MongoChef
下载:http://3t.io/mongochef/#mongochef-download-compare
*/
// ----------------------------------------------------------------------------
//-------------------------------------- Linux版 -------------------------------
// Mongodb 需要64位linux 本次使用ubuntu18.0.4 如果是centos,某些命令会不同。
// 到官网下载tar包 tgz, 注意选择OS版本
// https://www.mongodb.com/download-center
tar zxvf mongodb-linux-x86_64-3.6.4.tgz
mv mongodb-linux-x86_64-3.6.4 mongodb364
cd mongodb364
// 建立所需的db文件夹和logs文件夹,在根目录创建,是因为停止服务时,不带参数,会默认寻找此路径
mkdir -p /data/db
mkdir -p /data/logs
// 修改环境变量,vim /etc/profile 添加
export PATH=/home/mongodb364/bin:$PATH
source /etc/profile // 生效
// ------------如果不能启动服务,ubuntu18 可能需要安装某些依赖。--------------
// 如果 apt-get 出现 E: Unable to locate package 问题, 则执行以下命令:
add-apt-repository main
add-apt-repository universe
add-apt-repository restricted
add-apt-repository multiverse
apt-get update
// 如果不能解决,再执行这条:
apt-get upgradee
// 移除某个包:
apt-get remove xxx
// 错误: libcurl.so.4: version `CURL_OPENSSL_3' not found
apt-get install curl
apt-get install libcurl3
// CentOS的依赖
yum install libcurl openssl // 安装依赖
// 启动服务 指定路径 --port 10086 指定端口
bin/mongod --dbpath=/opt/mongodb/data/db --logpath=/opt/mongodb/logs/mongo.log --fork bin/mongo --help // 使用客户端帮助
bin/mongo // 首次本机登录无需认证 bin/mongod --config /etc/mongod.conf // 或者指定配置文件启动,通常在设置安全后 // 停止服务 mongod --shutdown // 不指定dbpath, 默认会寻找 /data/db
// 停止服务 mongod --shutdown --dbpath /home/mongodb364/data/db // 指定dbpath
// 停止服务 mongod --shutdown --config=/etc/mongod.conf // 也可指定配置文件
/************* 安全性流程:
1.创建超级管理员
2.修改配置文件,启用身份验证
3.重启服务
4.使用超级管理员登录
5.创建并使用普通用户
*************/
// -------------------------------使用配置文件:--------------------------
vim /etc/mongod.conf // 较简单的格式
bind_ip = 0.0.0.0
port=27017
dbpath=/data/db
logpath=/data/logs/mongod.log
pidfilepath=/opt/mongodb/mongod.pid
fork=true
logappend=true
auth=true
// ---------------------------YAML格式配置文件--------------------------
如果是 rpm / yum 方式安装,则自动添加 /etc/mongo.conf ,示例:
# mongod.conf # for documentation of all options, see:
# http://docs.mongodb.org/manual/reference/configuration-options/ # where to write logging data.
systemLog:
destination: file
logAppend: true
path: /data/logs/mongod.log # Where and how to store data.
storage:
dbPath: /data/db
directoryPerDB: true
journal:
enabled: true
# engine:
# mmapv1:
# wiredTiger: # how the process runs
processManagement:
fork: true # fork and run in background
pidFilePath: /opt/mongodb/mongod.pid # location of pidfile
timeZoneInfo: /usr/share/zoneinfo # network interfaces
net:
port: 27017
bindIp: 127.0.0.1 # Enter 0.0.0.0,:: to bind to all IPv4 and IPv6 addresses or, alternatively, use the net.bindIpAll setting. security:
authorization: "enabled"
#operationProfiling: #replication: #sharding: ## Enterprise-Only Options #auditLog: #snmp:
bin/mongod --config /etc/mongod.conf // 指定配置文件启动
// 如果启动失败,请检查配置中文件路径是否正确
//------------------------配置远程连接---------------------------------
systemctl status ufw // 查看防火墙状态
systemctl stop ufw // 停止防火墙
ufw allow // 防火墙允许端口
// --------上面是ubuntu的,下面是centos7的。--------------------------
firewall-cmd --permanent --add-port=/tcp // 添加3306
systemctl restart firewalld.service // 重启fw
firewall-cmd --list-all // 查看fw
如果需要,也可将Mongodb安装为服务,便于管理
############# 在 CentOS7 中安装为服务
# 1. 创建用户和组
groupadd -g mongogrp
useradd -u -g mongogrp -G mongogrp mongouser
passwd mongouser # 2. 更改mongodb文件夹拥有者
chown -R mongouser:mongogrp mongod/ # 3.编辑服务文件 /etc/systemd/system/mongod.service 并保存
# 写User和Group是限制指定用户可以操作
[Unit]
Description=MongoDB Server
After=network.target remote-fs.target nss-lookup.target [Service]
User=mongouser
Group=mongogrp
Type=forking
ExecStart=/data/mongod/bins/mongod -f /data/mongod/conf/mongod.conf
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/data/mongod/bins/mongod --shutdown -f /data/mongod/conf/mongod.conf
PrivateTmp=true
LimitFSIZE=infinity
LimitCPU=infinity
LimitAS=infinity
LimitNOFILE=64000
LimitNPROC=64000 [Install]
WantedBy=multi-user.target
# 4. 试试用 mongouser 操作服务
sudo systemctl daemon-reload
sudo systemctl start mongod
sudo systemctl status mongod
sudo systemctl stop mongod
sudo systemctl enable mongod # 开机启动
sudo systemctl disable mongod # 关闭开机启动
sudo systemctl is-enabled mongod # 检查是否开机启动
sudo systemctl kill mongod # 杀死进程mongod sudo systemctl list-units -t service # 列出已激活的服务
sudo systemctl list-units -t service -a # 列出所有服务
//########################### mongo shell ####################################
mongo // 登录本机(未开启认证时)
// 执行以下命令,可以添加 管理员
use admin;
db.createUser(
{
user: "admin",
pwd: "admin",
roles: [ { role: "root", db: "admin" } ]
}
); /** 下面是成功时返回的提示:
Successfully added user: {
"user" : "admin",
"roles" : [
{
"role" : "userAdminAnyDatabase",
"db" : "admin"
}
]
};
**/
db.auth("admin","admin") // 认证测试,若 1 则成功 //----------------------------------------------------------------------------- // 如开启认证:
use admin // 进入管理库
db.auth("username","pwd") // 认证登录 // 或直接认证连接: 本地方式
mongo --username admin --password --authenticationDatabase admin
mongo -u admin -p --authenticationDatabase admin
// 远程方式
mongo "mongodb://admin:pwd@localhost:27017/?authSource=admin"
// 更多连接实例
// 参考: https://www.mongodb.org.cn/tutorial/7.html //连接本地数据库服务器,端口是默认的。
mongodb://localhost
//使用用户名fred,密码foobar登录localhost的admin数据库。
mongodb://fred:foobar@localhost
//使用用户名fred,密码foobar登录localhost的baz数据库。
mongodb://fred:foobar@localhost/baz //连接 replica pair, 服务器1为example1.com服务器2为example2。
mongodb://example1.com:27017,example2.com:27017
//连接 replica set 三台服务器 (端口 27017, 27018, 和27019):
mongodb://localhost,localhost:27018,localhost:27019
//连接 replica set 三台服务器, 写入操作应用在主服务器 并且分布查询到从服务器。
mongodb://host1,host2,host3/?slaveOk=true
//直接连接第一个服务器,无论是replica set一部分或者主服务器或者从服务器。
mongodb://host1,host2,host3/?connect=direct;slaveOk=true
//当你的连接服务器有优先级,还需要列出所有服务器,你可以使用上述连接方式。 //安全模式连接到localhost:
mongodb://localhost/?safe=true
//以安全模式连接到replica set,并且等待至少两个复制服务器成功写入,超时时间设置为2秒。
mongodb://host1,host2,host3/?safe=true;w=2;wtimeoutMS=2000
// Shell 常用操作
db
show dbs
show collections
use local
show users // 查看当前库中用户
db.test.insert({'a':''}) // 插入数据时会自动创建库和Collections
db.test.find() // 显示所有数据 exit // 退出mongo shell // 最后用Robo 3T 测试连接
/*************** 如果需要重置密码: ***************/
// 1. 停止服务 mongod --shutdown --config=/etc/mongod.conf
// 2. 修改conf文件,关掉security和authorization
// 3. 启动服务 mongod --config /etc/mongod.conf
// 4. mongo 登录,use admin ,
show users // 显示本库用户
db.system.users.find() // 查看全部用户信息。
db.dropUser(用户名) // 删除指定的用户
// 5. 使用上面的 db.createUser 添加用户:
use admin
db.createUser(
{
user: "admin",
pwd: "admin",
roles: [ { role: "root", db: "admin" } ]
}
); // 或者修改用户:
db.updateUser('admin',
{
pwd: "admin",
roles: [{ role: "root", db: "admin" } ]
}
)
// 6. 重新开启配置文件的安全选项,并重启服务
/*********** Mongodb内置的用户角色:
1. 数据库用户角色:read、readWrite
2. 数据库管理角色:dbAdmin、dbOwner、userAdmin
3. 集群管理角色:clusterAdmin、clusterManager、clusterMonitor、hostManager
4. 备份恢复角色:backup、restore
5. 所有数据库角色:readAnyDatabase、readWriteAnyDatabase、userAdminAnyDatabase、dbAdminAnyDatabase
6. 超级用户角色: root (最大权限,可访问所有库)
间接或直接提供了系统超级用户访问的角色:dbOwner、userAdmin、userAdminAnyDatabase
7. 内部角色:__system
# 创建一个 __system 用户,可以访问 所有元数据
db.createUser({user:"sa", pwd:"123456", roles:[{role:"__system", db:"admin"}]})
获得数据库的所有用户权限信息:db.getUsers()
获得某个用户的权限信息:db.getUser()
创建角色: db.createRole()
更新角色:db.updateRole()
删除角色:db.dropRole()
获得某个角色信息:db.getRole()
删除用户:db.dropUser()
删除所有用户:db.dropAllUsers()
将一个角色赋予给用户:db.grantRolesToUser()
撤销某个用户的某个角色权限:db.revokeRolesFromUser()
更改密码:db.changeUserPassword()
***********/
// 例1:给test库添加用户,只能访问test 即 --authenticationDatabase test
use test
db.createUser(
{
user: "test1",
pwd: "test1",
roles: [ { role: "readWrite", db: "test" } ]
}
); // 例2:修改user1权限 --authenticationDatabase demo
use demo
db.updateUser('user1',{
roles: [{role:"dbOwner", db:"demo"}]
}) // 例3:修改test用户权限,读写所有库
use admin
db.updateUser('test',{
roles: [{role:"readWriteAnyDatabase", db:"admin"}]
}) /************ 其它命令 ******
创建 capped collection 上限集合:
size:大小KB,如果size字段小于或等于4096,则集合的上限为4096字节
max: 最大文档数。size参数总是必需的,即使指定max的文件数量。
如果集合在达到最大文档计数之前达到最大大小限制,MongoDB将删除旧文档。
参考官方文档 或 https://www.jianshu.com/p/86942c09094a
************/
db.createCollection("sub",{capped:true,size:,max:}) db.sub.isCapped() // 检查是否 capped // 转换为 capped 集合
db.runCommand({"convertToCapped": "test", size: , max: });
/**************
*** CURD ***
**************/
//----------------------------------- 增 ---------------------------------------
// Mongodb 数据库名称不区分大小写
// 数据库不必创建,直接 use databasename 即可
// 集合名称可以createCollection创建,
// 一般集合也可不创建,直接在插入数据时自动生成。
// 集合名称只能字母或下划线开头,不能包含 . $ 和空字符,不能 system. 开头
// 更多限制,参考官文:https://docs.mongodb.com/manual/reference/limits/
// 插入多条
db.users.insert([
{name:'Allan',age:,gender:},
{name:'Bob',age:,gender:},
{name:'Celine',age:,gender:},
{name:'Dennis',age:,gender:},
]) // 以下两种插入方法是为了语义清晰
// db.test.insertOne()
// db.test.insertMany() // ================================== 查 =======================================
db.test.find({}) // 空对象或空,查询所有的
db.test.find({name:"Jerry"}) // 返回数组
db.test.findOne({name:"Jerry"}) // 返回对象
db.test.find({}).count() // 数量 或 db.test.count()
db.users.count({age:{$gt:}}) // 条件数量
db.test.find({age:{$gt:}}) // 大于 或者 $gte 即 >=
db.test.find({create_ts:{$gt:ISODate("2019-09-19T00:00:00.000Z")}}).pretty() //大于某时间
db.test.find({age:{$eq:}}) // 等于 或者 $ne 不等于
db.test.find({age:{$lt:}}) // 小于 或者 $lte 即 <=
db.test.find({age:{$gt:, $lt:}}) // 大于且小于
db.demoes.find({$or:[{num:{$lt:}},{num:{$gt:}}]}) // 或 $or:[{},{},]
db.users.find({age:{$in:[,]}}) // 在in 或 不在nin
db.users.find({name:/^C/}) // 正则,以C开头
db.users.find({name:{$regex:"^A"}}) // 正则, 以A开头
db.users.find({nickname:{$exists: false}}) // 找出不存在昵称字段的 (true 存在)
// 虽然可用JS语法,但是效率低
db.users.find({$where:function(){return this.age>}})
db.users.find({$where:function(){return this.name.startsWith("C")}}) db.test.find().limit() // 前10条
db.test.find().skip().limit() // 跳过10条
// 官方文档也提到 skip() 由于是从头开始数,所以,当数据量变大时,会变得非常慢。
// 我测试的时候,大于5万条数据,已经很慢了。 所以,尽量使用 条件查询,避免使用 skip() // skip( (页码 -1) * 每页条数).limit(每页条数)
// limit()与skip()或sort() 前后无关,mongodb自动调整 db.test.find().sort({age:-}) // 按年龄降序 // 1取0不要,只有_id需要特别指定为0
db.test.find({},{name:, _id:, age:}) // 投影:只要name和age,不要_id
db.users.distinct("gender", {age:{$lt:}}) // 年龄小于20的性别 // --------------------------------- 改 ----------------------------------------
// db.test.update({_id:ObjectId("5cede5d81f3b03073319abd0")},{age:23}) // 小心,新对象替换旧对象
// 应该使用修改符来操作
db.test.update({_id:ObjectId("5cede5d81f3b03073319abd0")},{$set:{name:"老沙", gender:"男",address:"流沙河"}})
db.test.update({_id:ObjectId("5cede5d81f3b03073319abd0")},{$set:{age:}})
db.test.update({_id:ObjectId("5cede5d81f3b03073319abd0")},{$unset:{address:}}) // 删除某字段 只删除第一个匹配到的
// $unset 删除字段时,字段写什么值并不影响结果。
db.test.update({},{$unset:{"Profiles":""}},{multi:true}) // 删除了所有的 Profiles 字段
// db.test.update({},{$unset:{"Profiles":""}})
db.test.update({},{$unset:{"Qr":"SOCKET_EMPTY"}},{multi:true}) // 删除所有的 Qr 字段
db.test.update({name:"AAAA"},{$set:{address:"test"}}) // 默认只改一条
db.test.update({name:"AAAA"},{$set:{address:""}},{multi:true}) // 使用multi改所有的 db.test.updateMany({name:"AAAA"},{$set:{address:""}}) // 改所有符合的
db.posts.updateMany({created_at:{$exists:false}},{$set:{created_at:'2019-07-08 16:20:00'}}) // 不存在某字段时,加上 /* ********************************* 删 ****************************************/
db.test.remove({address:""}) // 默认删除全部匹配的行
db.test.remove({address:""}, true) // 只删除一行
db.test.remove({},true) // 删除第一行
db.test.remove({}) // 清空集合 db.test.drop() // 删除集合
db.dropDatabase() // 删当前库(赶紧跑路) // 通常上面的都不会执行, 使用字段isDel代替
db.test.updateOne({name:"AAAA"},{$set:{isDel:}})
db.test.find({isDel:})
// $type 操作符 https://www.mongodb.org.cn/tutorial/15.html
db.test.find({"title" : {$type : 2}}) // 条件:字段为string类型
// -----------#-----------#----------- 练习 ------#-----------#-----------#-------
// 属性值也可以是个文档 即 内嵌文档
db.goods.update({name:"CPU"},{$set:{band:{Intel:["I3","I5","I7"],AMD:["R5","R7"]}}})
db.goods.find({'band.AMD':'R5'}) // 查询内嵌时必须引号, 包含
db.goods.find({'band.AMD':'R5'},{'band.AMD.$':1}) // 仅取出AMD.R5的列表元素,不要其它的元素。 db.goods.update({name:"Mem"},{$push:{'band.KST':''}}) // 插入一个,可重复
db.goods.update({name:"Mem"},{$addToSet:{'band.KST':''}}) // 添加到集合,不重复
db.goods.update({name:"Mem"},{$pop:{'band.KST':}}) // 移除最后一个元素 //# 插入20000条数据
// 1. 笨方法:
for(var i=; i<;i++){
db.demos.insert({num:i})
} // 2. 好方法:
var arr=[];
for(var i=; i<;i++){
arr.push({num:i});
}
db.demoes.insert(arr)
文档间关系
//# 1. 一对一:通过内嵌文档的形式.
db.married.insert([
{name:"Tom",guy:{name:"Jerry"}},
{name:"大郎",guy:{name:"金莲"}}
]) //# 2. 一对多, 多对一:
db.users.insert([
{username:"swk"},
{username:"zbj"}
]) db.order.insert([
{list:["CPU","Mem","Disk"],
user_id: ObjectId("5cef98a9e4a985f4ad3e897c")
},
{list:["Apple","Pear","Cherry"],
user_id: ObjectId("5cef98a9e4a985f4ad3e897c")
}
]) db.order.insert(
{list:["Pig","Donkey","Sheep"],
user_id: ObjectId("5cef98a9e4a985f4ad3e897d")
}) // 查询
var user_id=db.users.findOne({username:"swk"})._id;
db.order.find({user_id:user_id}) //# 3. 多对多:
db.teacher.insert([
{name:"如来"},
{name:"观音"},
{name:"菩提"}
]) db.students.insert([
{"name" : "Tom",
"teacher_ids" : [
ObjectId("5cefbdffe4a985f4ad3e8984"),
ObjectId("5cefbdffe4a985f4ad3e8982")
]},
{"name" : "Jerry",
"teacher_ids" : [
ObjectId("5cefbdffe4a985f4ad3e8984"),
ObjectId("5cefbdffe4a985f4ad3e8983")
]}
]) // 查询: 如来的徒弟
var tid = db.teacher.find({name:"如来"})[]._id // 或
var tid = db.teacher.findOne({name:"如来"})._id
db.students.find({teacher_ids:tid}) //-----------------#----------------- 练习 ------------------#-------------------
// 1. 找出财务部员工
var deptno = db.dept.findOne({dname:"财务部"}).deptno
db.emp.find({deptno:deptno}) // 2. 低于1000的加400
db.emp.updateMany({sal:{$lt:}},{$inc:{sal:}})
db.emp.updateMany({deptno:},{$inc:{sal:}}) // IT部加工资 // 3. 价高于300的减100
db.goods.updateMany({price:{$gt:}},{$inc:{price:-}})
管道
// aggregate 用于聚合统计,$group 类似于SQL的sum(), avg() // 各求男女人数
db.users.aggregate([{$group:{_id:'$gender',counter:{$sum:}}}]) db.users.aggregate([{$group:{_id:'$gender',counter:{$sum:'$age'}}}]) // 年龄合计
db.users.aggregate([{$group:{_id:'$gender',counter:{$avg:'$age'}}}]) // 平均年龄
db.users.aggregate([{$group:{_id:'$gender',counter:{$max:'$age'}}}]) // 或 min
db.users.aggregate([{$group:{_id:'$gender',counter:{$first:'$age'}}}]) // 或 last // 列出各年龄到数组,不去重
db.users.aggregate([{$group:{_id:'$gender',counter:{$push:'$age'}}}]) // 男女分组,列出name到数组
db.users.aggregate([{$group:{_id:'$gender',counter:{$push:'$name'}}}]) // 男女分组,基于整个文档列出所有字段到数组
db.users.aggregate([{$group:{_id:'$gender',counter:{$push:'$$ROOT'}}}]) //## $match
db.users.aggregate([{$match:{age:{$gt:}}}]) // 筛选 // 将筛选后的结果再聚合
db.users.aggregate([
{$match:{age:{$gt:}}},
{$group:{_id:'$gender',counter:{$sum:}}}
]) // 筛选,聚合,投影
db.users.aggregate([
{$match:{age:{$gt:}}},
{$group:{_id:'$gender',counter:{$push:'$name'}}},
{$project:{_id:,counter:}}
]) // 排序,和find()中的几乎一样 {$sort:{_id: -1}} 也可以用在多个地方
db.users.aggregate([
{$match:{age:{$gt:}}},
{$sort:{name: }},
{$group:{_id:'$gender',counter:{$push:'$name'}}},
{$sort:{_id:-}}
]) // 内按name升序,外按_id降序 // 跳过 {$skip:10},限制{$limit:5} 此处区分顺序 /**
* {$unwind:"$counter"} 将数组字段拆开成单条
*/
db.students.aggregate([
{$match:{name:"WuKong"}},
{$unwind:"$teacher_ids"}
]) db.t3.insert([
{"_id":,"item":"a","size":["S","M","L"]},
{"_id":,"item":"b","size":[]},
{"_id":,"item":"c","size":"M"},
{"_id":,"item":"d"},
{"_id":,"item":"e","size":null},
]) db.t3.aggregate([{$unwind:{path:"$size"}}]) // 取出值 不含空和null以及无字段 // 取出值,不丢任何数据
db.t3.aggregate([
{$unwind:{path:"$size", preserveNullAndEmptyArrays:true}}
]) // 示例1:找出几个字段组合的重复数据
db.products.aggregate([
{
'$group': {
'_id': {
'Product': '$Product',
'Machine': '$Machine',
'Station': '$Station',
'Status': '$Status',
'Price': '$Price'
},
'uniqueIds': {
'$addToSet': '$_id'
},
'count': {
'$sum': 1
}
}
},
{
'$match': {
'count': {
'$gt': 1
}
}
}],
{
allowDiskUse: true
});
// 示例2: 排除某个状态的重复数据查找
db.members.aggregate([
{'$match': {'Status': {'$ne': '-1'}}},
{
'$group': {
'_id': {
'Station': '$Station',
'Name': '$Name'
},
'uniqueIds': {
'$addToSet': '$_id'
},
'count': {
'$sum': 1
}
}
},
{
'$match': {
'count': {
'$gt': 1
}
}
}
], {
allowDiskUse: true
});
索引
/********************************** 索引 **************************************/
db.t1.ensureIndex({name:}) // 添加索引
db.t1.ensureIndex({name:}, {unique:true}) // 多参数
db.t1.ensureIndex({name:,age:}) // 联合索引
db.t1.getIndexes() // 查询索引
db.t1.dropIndex("name_1") // 删除指定索引
db.t1.dropIndexes() // 删除全部索引,保留默认 _id_ 索引 // 测试数据
let arr=[];
for(let i=;i<;i++){
arr.push({name:"test"+i, age:i});
}
db.t1.insert(arr) // 性能评估 其中结果 executionTimeMillis 为毫秒
db.t1.find({name:'test9999'}).explain('executionStats') db.t1.ensureIndex({name:}) // 添加索引 // 再次执行 结果 executionTimeMillis 降低很多
db.t1.find({name:'test9999'}).explain('executionStats') // 删除数据时,索引不会删除,并且体积可能变得更大,必要时可以删除索引,重建索引。
/*************************** 复制集 ******************************/
// 官文 https://docs.mongodb.com/manual/replication/
主备
// 例1:单机演示。(生产环境不适用)使用不同端口,不同数据目录,必须设置相同 replSet
mongod --bind_ip 192.168.112.9 --port --dbpath /data/t1 --replSet rs0
mongod --bind_ip 192.168.112.9 --port --dbpath /data/t2 --replSet rs0
// 服务运行窗口可以看到后续操作的日志显示 // 然后客户端分别连接服务
mongo --host 192.168.112.9 --port
rs.initiate() // 初始化为master 提示符发生变化
rs.status() // 查看复制集状态 rs0:PRIMARY>
rs.isMaster() // 是否主节点
rs.add("192.168.112.9:27019") // 添加slave mongo --host 192.168.112.9 --port
rs.slaveOk() // slave上执行同意 // 例2:不同机器(接近生产环境)。必须设置相同 replSet
// 注意OS版本,rs1:PRIMARY 可低版本,rs1:SECONDARY可高版本。反之则rs.add出错
// 本例PRIMARY为112.6(centos6.5), SECONDARY为112.9(centos7.5)
mongod --bind_ip 192.168.112.6 --port --dbpath /data/t3 --replSet rs1
mongod --bind_ip 192.168.112.9 --port --dbpath /data/t3 --replSet rs1 // 使用客户端分别连接服务
mongo --host 192.168.112.6 --port
mongo --host 192.168.112.9 --port rs.initiate() // 112.6 为 master
rs.status() // 查看复制集状态 rs1:PRIMARY>
rs.add("192.168.112.9:27018") // 添加slave rs.slaveOk() // 112.9 上执行同意 // 测试数据 master
use demo1
db.users.insert({name:"Allen",age:})
db.users.insert({name:"Bob",age:}) // slave上查询
use demo1
db.users.find() // 得到相同结果 // 发现master当机后,某slave则自动变为PRIMARY
// 而修好后的master启用,加入到rs1,转为SECONDARY
/////////////////////// 添加一个节点(192.168.112.7:27017)
// 新节点 安装,添加目录,然后执行:
mongod --bind_ip 192.168.112.7 --port 27017 --dbpath /data/t3 --replSet rs1
// 然后 rs1:PRIMARY> 上执行:
rs.add("192.168.112.7:27017") // 添加slave节点
// slave 新窗口上执行:
mongo --host 192.168.112.7 --port 27017
> rs.slaveOk() // 即可自动更新所有数据 /////////////////////// 删除一个节点
rs1:PRIMARY> rs.remove("192.168.112.6:27018") // 被删节点将不可用 /////////////////////// 停止节点服务
mongod --bind_ip 192.168.112.7 --port 27017 --dbpath /data/t3 --shutdown // 其它命令:
rs.conf() // 显示复制集信息
rs.printReplicationInfo() // 从primary角度显示复制集信息,显示 oplog 信息
rs.printSlaveReplicationInfo() // 从secondary角度显示复制集信息
db.serverStatus().asserts // 查看断言
rs.stepDown() // 强制primary降为secondary,并引发新的选举. 慎用
#故障案例:某个 slave 节点自动down掉,再次启动时过一会还是down掉,检查日志后发现:
[replication-0] We are too stale to use 10.1.1.34:27017 as a sync source. Blacklisting this sync source because our last fetched timestamp:
Timestamp(1584041941, 30) is before their earliest timestamp: Timestamp(1584399943, 455) for 1min until:
解决办法:将此 slave 停止服务, 改名或删除 mongodb 仅数据目录后,重新启动 mongodb, 如果状态显示为 startup2 则表示成功开始同步数据。等待同步完成即可恢复正常。
备份与恢复
// mongodump -h dbhost -d dbname -o outdir
// 备份将在输出目录中生成Collection对应的 bson 和 metadata.json 文件
mongodump -u admin -p admin --authenticationDatabase admin -h 192.168.112.9 -d test -o /bak/mongodb // 恢复 mongorestore -h dbhost -d dbname --dir inputdir
mongorestore -u admin -p admin --authenticationDatabase admin -h localhost -d test --dir /bak/mongodb/test/
Python pymongo
// driver for python
pip3 install pymongo
/*************************************** demo.py ******************************/
#!/usr/bin/env python
# coding:utf-8 from pymongo import * client = MongoClient('mongodb://test1:test1@192.168.112.9:27017/test') db = client.test # 库
users = db.users # Collections # res = users.insert({'name':'python','age':88,'gender':'female'}) # 插入
# print(res) # 返回 id
# ret = users.insert_one({'name':'pip3','age':19,'gender':'male'}) # 插入
# print(ret) # 返回 object # ret2 = users.update_one({'name':'python'},{'$set':{'name':'Python3'}}) # 修改
# print(ret2) # ret3 = users.delete_one({'name':'pip3'}) # 删除
# print(ret3) # cursor = users.find_one({'name':'Python3'}) # 只取一条
# print(type(cursor), cursor)
# for k, v in cursor.items():
# print(k + " --> " + str(v)) # cursor = users.find({'age':{'$gt':30}}) # 取多条
# for s in cursor:
# print(s)
# # print(s['name'], s['age']) # cursor = users.find().sort([('gender',1),('age',-1)]) # 多条件降序
# for s in cursor:
# print(s) cursor = users.find().sort('age',-1).limit(2).skip(3) # 子集
for s in cursor:
print(s)
Node.js mongoose
因为npm 库中的 mongodb没有这个好用,所以直接使用 mongoose
/**
1. 安装
npm i mongoose --save 2. 引入
let mongoose = require("mongoose"); 3. 连接数据库
mongoose.connect('mongodb://root:123456@192.168.112.9/odm_demo?authSource=admin',{useNewUrlParser:true});
默认27017可以省略
通常只需连接一次,除非项目停止或服务器关闭,否则连接一般不会断开。 4. 断开连接(一般不需要)
mongoose.disconnect();
一般情况下,只需要连接一次; 除非项目停止服务器关闭,否则连接一般不会断开 - 监听Mongodb连接状态
- 在mongoose对象中,有一个属性叫做connection 表示的就是数据库连接
通过监视该对象的状态,可以来监听数据库的连接与断开 - 连接成功事件
mongoose.connection.once("open",function(){}); - 数据库断开事件
mongoose.connection.once("close",function(){});
*/ const mongoose = require('mongoose'); mongoose.connect('mongodb://admin:admin@192.168.112.9/admin', {useNewUrlParser: true}); // 正确写法 mongoose.connection.once('open',function () {
console.log("连接成功.");
}); mongoose.connection.once('close',function () {
console.log('数据库已断开.');
}); mongoose.disconnect(); // 一般不会调用
mongoose demo
const mongoose = require('mongoose'); mongoose.connect('mongodb://root:123456@192.168.112.9/odm_demo?authSource=odm_demo',{useNewUrlParser:true});
mongoose.connection.once('open',function (err) {
if(err){
console.log(err);
}else{
console.log("连接成功~~~");
}
}); /**
* Schema
* Model
* Document
*/ // 1. 定义 Schema
let Schema = mongoose.Schema; // 2. 创建模式(约束) Schema 对象
let stuSchema = new Schema({
name: String,
age: Number,
gender:{
type: String,
default:"female"
},
address:String
}); // 3. 通过Schema创建 Model (Collection),通过Model才能操作数据库
let StuModel = mongoose.model("child", stuSchema); // 集合名自动变复数 // 4. 插入文档 Model.create(doc,function (err) {});
StuModel.create({
name:"紫霞仙子",
age:18,
// gender:"male",
address:"水帘洞"
},function (err) {
if(!err){
console.log("插入成功.");
}
});
模型用法示例
require("./common/conn_mongo");
let StuModel = require('./model/users'); // 插入 Model.create(doc(s),[callback])
/* StuModel.create([
{
name:"沙和尚",
age:42,
gender:"male",
address:"流沙河"
}
],function (err) {
if(!err){
// console.log('插入成功~~~');
console.log(arguments); // 返回插入的内容
}
}); StuModel.create(
[{
name:'白骨精',
age:90,
address:'山洞'
},{
name:'女王',
age:38,
address:'女儿国'
}], function (err) {
if(!err){
console.log('插入成功.')
}
}
); */ /** 查询:
* Model.find(conditions,[projection],[options],[callback])
* 查询所有符合条件的文档 返回数组
* Model.findById(id,[projection],[options],[callback])
* 根据ID属性查询文档
* Model.findOne([conditions],[projection],[options],[callback])
* 查询符合条件的第一个文档
*
* Model.count(conditions, [callback]) // 数量
*
* - projection 投影 想要的字段
* 两种方式: {name:1, _id:0}
* "name -_id"
* - options 选项(skip, limit )
* {skip:2, limit:1}
* - callback 回调函数 必传, 不传则不会查询
*/ // StuModel.count({},function (err, count) { // count 是旧方法
StuModel.countDocuments({},function (err, count) { // 新方法
if(!err){
console.log(count);
}
}); StuModel.find({name:"八戒"},function (err,docs) { // 返回数组
if(!err){
if(docs.length > 0){
console.log(docs)
// console.log(docs[0].name)
}else{
console.log('docs is empty')
}
}
}); StuModel.findOne({name:"唐僧"},function (err, doc) { // 返回文档对象, 就是Document
if(!err){
if(doc){
// console.log(doc)
console.log(doc.address);
console.log(doc instanceof StuModel) // Document对象是Model的实例
}else{
console.log('no result')
}
}
}); StuModel.findById('5d108a9fe15d35242c37666c',function (err, doc) {
if(!err){
console.log(doc.name);
}
}); // // 投影 只取name age 不要 _id
// StuModel.find({},{name:1, age:1, _id:0},function (err, docs) { // 对象参数
StuModel.find({},'name age -_id', {skip:1,limit:1}, function (err, docs) { // 字符串参数
if(!err){
if(docs.length > 0){
console.log(docs)
}
}
}); /** 修改
* Model.update(conditions, doc, [options], [callback])
* Model.updateMany(conditions, doc, [options], [callback])
* Model.updateOne(conditions, doc, [options], [callback])
* Model.replaceOne(conditions, doc, [options], [callback])
* - conditions 查询条件
* - doc 修改后的对象
*/ StuModel.updateOne({name:"唐僧"},{$set:{age:77}},function (err) {
if(!err){
console.log('修改成功.');
}
}); /** 删除 一般不用
* Model.remove(conditions, [callback])
* Model.deleteOne(conditions, [callback])
* Model.deleteMany(conditions, [callback])
*/ // StuModel.deleteOne({name:'白骨精'},function (err) {
// if(!err){
// console.log('删除成功.')
// }
// });
common/conn_mongo.js
let mongoose = require("mongoose"); mongoose.connect('mongodb://admin:admin@192.168.112.9/odm_demo?authSource=admin',{useNewUrlParser:true});
mongoose.connection.once('open',function (err) {
if(err){
console.log(err);
}else{
console.log("连接成功~~~");
}
});
model/users.js
/**
定义模型
*/ const mongoose = require('mongoose');
let Schema = mongoose.Schema; let stuSchema = new Schema({
name: String,
age: Number,
gender:{
type: String,
default:"female"
},
address:String
}); // 有了model 即可CURD
let UsrModel = mongoose.model("users", stuSchema); // 如果是复数,则名称不变
module.exports = UsrModel;
文档用法示例:
require('./common/conn_mongo');
let monster = require('./model/monster'); /**
* Document 和 集合中的文档一一对应,Document是Model的实例
* 通过 Model 查询到的结果都是 Document
*/
let stu = new monster({
name:"奔波儿霸",
age:888,
gender:"male",
address:"碧波潭"
}); // console.log(stu); // Document对象的方法 Model#save([options],[fn])
// 而 create 是 Model 的方法
// stu.save(function (err) {
// if(!err){
// console.log("写入成功~")
// }
// }); monster.findOne({},function (err, doc) {
if(!err){
/**
* update(update,[options],[callback]))
* - 修改对象
* save([callback]))
* update([callback]))
*/
// console.log(doc);
// doc.update({$set:{age:22}},function (err) { // 过时的方法
// if(!err){
// console.log("修改成功.")
// }
// }); // doc.updateOne({$set:{address:"高老庄"}},function (err) {
// if(!err){
// console.log("修改成功");
// }
// }); // // 直接修改
// doc.age = 2000;
// doc.save(); // 删除
// doc.remove(function (err) {
// if(!err){
// console.log("师傅再见~")
// }
// }) /**
* get(name)
* set(name, value)
* id 获取文档的 _id 属性
* toJSON()
* toObject() document对象方法则失效
*/
console.log(doc.get("name"));
console.log(doc.address); // doc.set("name","猪悟能"); // 需要 save() 才能修改数据库
// doc.name = "奔波霸";
// doc.save();
console.log(doc.id); console.log(typeof doc); // Object
let t = doc.toObject(); // 转为普通 JS 对象
delete t.__v;
delete t._id;
console.log(t);
}
});
model/monster.js
const mongoose = require('mongoose');
let Schema = mongoose.Schema;
let stuSchema = new Schema({
name: String,
age: Number,
gender:{
type: String,
default:"female"
},
address:String
}); let MonsterModel = mongoose.model("monsters", stuSchema);
module.exports = MonsterModel;
Mongodb基础 学习小结的更多相关文章
- MongoDB基础学习
*:first-child { margin-top: 0 !important; } body>*:last-child { margin-bottom: 0 !important; } /* ...
- mongodb基础学习2-基本CRUD
接着学习一下mongodb的基本的CRUD 先列出基本知识点,再给出相关的例子 增:语法: db.collectionName.insert(document); 1: 增加单篇文档,不指定_id时会 ...
- mongodb基础学习8-复制集
今天来简单学习一下复制集(replication),什么是复制集呢,类似于mysql的主从复制吧 简单来说就是有多个mongodb的实例,多个实例有相同的内容,其中一台用于读写,其它用于备份,当用于读 ...
- mongodb基础学习1-基本说明及安装
以前看过一些mongodb的视频,但只看到一半没有看完,也没有同步安装软件动手操作,正好最近没事,打算花点时间从头学习一遍,边学习边动手操作,学习的过程在此进行记录. 好了,下面说一下今天的学习内容. ...
- MongoDB基础学习(一) MongoDB概念解析
.基础概念 SQL术语/概念 MongoDB术语/概念 说明 database database 数据库 table collection 数据表/集合 row document 数据记录行/文档 c ...
- Mongodb分片 学习小结
前一篇 https://www.cnblogs.com/frx9527/p/mongodb.html 学会搭建复制集Replication之后,就可以学习分片Sharding了. 教程建议看官方文档: ...
- Java JDBC基础学习小结
JDBC是一个Java应用程序接口,作用是封装了对数据库的各种操作.JDBC由类和接口组成,使用Java开发数据库应用都需要4个主要的接口:Driver.Connection.Statement.Re ...
- Shell基础学习小结
0 shell基础概念 Shell是解释性语言,使用脚本编程语言的好处是,它们多半运行在比编译型语言还高的层级,能够轻易处理文件与目录之类的对象:缺点是它们的效率通常不如编译型语言.Shell命令有本 ...
- mongodb基础学习7-备份与恢复
下面来讲讲mongodb的备份与恢复 备份可以备份为二进制格式,如果是用于数据交换,可以备份成json或cvs格式 导入/导出可以操作的是本地的mongodb服务器,也可以是远程的. 所以,都有如下通 ...
随机推荐
- 【微学堂】线上Linux服务器运维安全策略经验分享
技术转载:https://mp.weixin.qq.com/s?__biz=MjM5NTU2MTQwNA==&mid=402022683&idx=1&sn=6d403ab4 ...
- 新版本的node,全局配置
配置环境变量: 1.在你安装node环境目录下 即是node_modules同级目录中. 创建两个文件夹[node_global]及[node_cache] node_cache:缓存目录 node_ ...
- 4. Go语言—值类型和引用类型
一.值类型 1. 定义 变量直接存储的值,内存通常在栈中分配: var i = 5 -> i-->5 2. 应用 int.float.bool.string.数组.struct 二.引 ...
- day80_10_29git冲突解决与短信服务redis
一.开发中的操作. 在项目开发中,在工作区进行开发,开发结束后提交到本地版本库. 再拉取远程仓库,具体如下: """ 1.开发前,拉一次远程仓库 2.工作区进行开发 3. ...
- Winform重写键盘按键事件
/// <summary> /// 重写键盘处理事件,处理退出和回车按钮 /// </summary> protected override bool ProcessCmdKe ...
- Manthan, Codefest 18 (rated, Div. 1 + Div. 2) F 单调栈 + 贡献 + 计数
https://codeforces.com/contest/1037/problem/F 题意 function z(array a, integer k): if length(a) < k ...
- 第02组 Beta冲刺(2/5)
队名:無駄無駄 组长博客 作业博客 组员情况 张越洋 过去两天完成了哪些任务 数据库实践 提交记录(全组共用) 接下来的计划 加快校园百科的进度 还剩下哪些任务 学习软工的理论课 学习代码评估.测试 ...
- COMP222 - 2019
COMP222 - 2019 - Second CA AssignmentIndividual courseworkTrain Deep Learning AgentsAssessment Infor ...
- 一.OS运行机制
运行机制: 1.中断(外部) =====一种通知行为(例如插入键盘) 2.系统调用(主动反应) ===一种请求行为 3.异常(内部) =====一种错误处理行为 系统调用和程序接口的关系,接口把系统调 ...
- 奥展项目笔记06--js弹出框、对话框、提示框、弹窗总结
JS的三种最常见的对话框: //====================== JS最常用三种弹出对话框 ======================== //弹出对话框并输出一段提示信息 functi ...