MongoDB笔记

1.简介

官网: https://www.mongodb.org

MongoDB是文档数据库,存储的是文档(Bson,json的二进制数据),内部执行引擎为JS解析器(谷歌v8),把文档储存成bson结构,在查询是转换为JS对象,可以通过熟悉的JS语法来操作。

MongoDB和传统数据库区别:

  • 传统数据库:结构化数据,设计了表结构后,每一行内容的列的类型是固定的。

  • MongoDB文档数据库:表下的每篇文档都可以有自己独立的数据结构(json对象都可以有自己独特的属性和值)。

2. 安装和启动MongoDB

2.1. 在主机安装MongoDB

(1) 安装MongoDB

# 下载地址https://www.mongodb.org/dl/linux/x86_64
# 下载双数版本,例如3.6,而单数3.5是开发版本

#下载
wget http://downloads.mongodb.org/linux/mongodb-linux-x86_64-3.6.3.tgz?_ga=2.249742406.1729791217.1523023903-593615807.1523023903

#解压并安装到/usr/local目录下
tar xvf mongodb-linux-x86_64-3.6.3.tgz
mv mongodb-linux-x86_64-3.6.3 mongodb
mv mongodb /usr/local

# 把bin目录添加到环境变量
echo 'export PATH="$PATH:/usr/local/mongodb/bin"' >> /etc/bashrc

# 使当前终端生效
source /etc/bashrc

# 创建存放数据和日志文件夹
mkdir -p /data/mongodb/db
mkdir -p /data/mongodb/log

mongodb安装bin目录下程序说明:

  • bsondump:导出bson结构
  • mongo:客户端
  • mongod:服务端
  • mongodump:整体数据库导出(二进制)
  • mongoexport:导出易识别的json文档或csv文档
  • mongorestore:数据库整体导入
  • mongos:路由器(分片时用)
  • mongostat:观察状态
  • mongotop:类似linux的top命令

(2) 启动MongoDB

以参数方式启动

mongod --dbpath /data/mongodb/db --logpath /data/mongodb/log/mongodb.log --port 27017 --fork
# --dbpath:数据库储存目录,--logpath日志储存目录,--fork后台运行,--port运行端口
# 使用mongod --help查看有哪些参数:
    # --dbpath 数据库路径(数据文件)
    # --logpath 日志文件路径
    # --master 指定为主机器
    # --slave 指定为从机器
    # --source 指定主机器的IP地址
    # --oplogSize 指定日志文件大小不超过64M.因为resync是非常操作量大且耗时,最好通过设置一个足够大的oplogSize来避免resync(默认的 oplog大小是空闲磁盘大小的5%)。
    # --logappend 日志文件末尾添加,即使用追加的方式写日志
    # --journal 启用日志
    # --port 启用端口号
    # --fork 在后台运行
    # --only 指定只复制哪一个数据库
    # --slavedelay 指从复制检测的时间间隔
    # --auth 是否需要验证权限登录(用户名和密码)
    # --syncdelay 数据写入硬盘的时间(秒),0是不等待,直接写入
    # --notablescan 不允许表扫描
    # --maxConns 最大的并发连接数,默认2000  
    # --pidfilepath 指定进程文件,不指定则不产生进程文件
    # --bind_ip 绑定IP,绑定后只能绑定的IP访问服务

自定义mongodb配置文件方式启动

新建配置文件:

vim /usr/local/mongodb/mongodb.conf

填写下面内容如下:

fork=true   # 允许程序在后台运行
#auth=true  # 开启认证
logpath=/var/log/mongo/mongo.log
logappend=true      # 写日志的模式:设置为true为追加。默认是覆盖
dbpath=/data/mongo/    # 数据存放目录
pidfilepath=/tmp/mongo/mongo.pid    # 进程ID,没有指定则启动时候就没有PID文件。默认缺省。
port=27017
bind_ip=127.0.0.1   # 绑定地址。默认127.0.0.1,只能通过本地连接

# 设置为true,修改数据目录存储模式,每个数据库的文件存储在DBPATH指定目录的不同的文件夹中。
# 使用此选项,可以配置的MongoDB将数据存储在不同的磁盘设备上,以提高写入吞吐量或磁盘容量。默认为false。
# 建议一开始就配置次选项
directoryperdb=true

# 禁止日志 
# 对应 journal 启用操作日志,以确保写入持久性和数据的一致性,会在dbpath目录下创建journal目录
nojournal=true

## max connections
# 最大连接数。默认值:取决于系统(即ulimit和文件描述符)限制。
# MongoDB中不会限制其自身的连接。当设置大于系统的限制,则无效,以系统限制为准。
# 设置该值高于连接池和总连接数的大小,以防止尖峰时候的连接。
# 注意:不能设置该值大于20000。
maxConns=1024

启动mongodb:

mongod -f /usr/local/mongodb/mongodb.conf

关闭mongodb服务:

mongod –shutdown –dbpath /data/mongodb/db

(3) 连接MongoDB

mongodb客户端连接:

mongo –host 192.168.8.200 –port 27017

有密码连接:

mongo -u “krislin” -p “123456” –host 192.168.8.200 –port 27017 –authenticationDatabase “crawler”

(4) 允许外网访问MongoDB

如果使用命令行方式启动,则添加参数–bind_ip 0.0.0.0;如果使用配置文件方式启动,则修改配置文件字段为bind_ip=0.0.0.0。

(5) 查看MongoDB连接数

netstat -nat | grep -i 27017 | wc -l

2.2. 在docker安装MongoDB

(1) 默认配置启动

docker run -d –name demo-mongo mongo:latest
docker run -d --name demo-mongo \
    -e MONGO_INITDB_ROOT_USERNAME=root \
    -e MONGO_INITDB_ROOT_PASSWORD=123456 \
    mongo

(2) 自定义配置文件启动

docker run -d –name demo-mongo -p 27017:27017 -v /data/mongo:/etc/mongo mongo –config /etc/mongo/mongod.conf

mongod.conf配置文件内容如下:

fork=true   # 允许程序在后台运行
#auth=true  # 开启认证
logpath=/var/log/mongo/mongo.log
logappend=true      # 写日志的模式:设置为true为追加。默认是覆盖
dbpath=/etc/mongo    # 数据存放目录
pidfilepath=/tmp/mongo/mongodb.pid    # 进程ID,没有指定则启动时候就没有PID文件。默认缺省。
port=27017
bind_ip=127.0.0.1   # 绑定地址。默认127.0.0.1,只能通过本地
directoryperdb=true
nojournal=true
maxConns=1024

(3) docker-compose命令启动,同时启动MongoDB管理界面服务

version: '3.1'
services:
  mongo:
    image: mongo
    restart: always
    environment:
      MONGO_INITDB_ROOT_USERNAME: root
      MONGO_INITDB_ROOT_PASSWORD: 123456
    ports:
    - 27017:27017
    volumes:
    - /data/mongo:/etc/mongo

  mongo-express:
    image: mongo-express
    restart: always
    ports:
      - 8081:8081
    environment:
      ME_CONFIG_MONGODB_ADMINUSERNAME: root
      ME_CONFIG_MONGODB_ADMINPASSWORD: 123456

3.MongoDB增删改查操作

3.1. 库和集合的基础命令

1. 库级命令

# 查看所有数据库
show dbs # 或使用mysql命令show databases;

# 切换到指定数据库
use 库名

# 创建数据库(mongodb不提供命令)
# mongodb的数据库是隐式创建的(创建表时自动创建),就算没有指定的库,也可以使用use命令。

# 删除数据库
db.dropDatabase()

2. 表(集合)级命令

# 显示所有表
show collections; # 或mysql命令show tables;

# 创建表
db.createCollection('user')

# 删除表
db.user.drop()

3.2. insert插入数据

1. 增加一个文档

# 不指定id
db.user.insert({name:'张三',age:22})

# 指定id
db.user.insert({_id:10001,name:'李四',age:23})

2. 一次增加多个文档

db.user.insert([{name:'张三',age:24},{_id:10002,name:'李四',age:25},{name:'王五',age:26}])

3.3. remove删除数据

语法:

db.collection.remove(查询表达式,选项)

查询表达式: 类似mysql的where条件,不加条件会删除表所有数据。 选项: 是否删除一行,{justOne:true/false},默认是false

# 示例
db.user.remove({_id:10001})
db.user.remove({age:24},{ justOne:true})

注:实际应用中一般不使用删除,使用一个字段来标记删除。

3.4. update修改数据

语法:

db.collection.updae(查询表达式,新值,选项)

错误示例:

db.user.update({name:‘张三’},{age:33})

注意:这种方式是新文档直接替换了旧文档,必须指定赋值表达式,常用表达式有:

表达式说明
$set设置字段新的值
$unset删除指定的列
$inc增长
$rename重命名该列
$setOnInsert当upsert时,设置字段的值

1. 赋值表达式

# $set设置字段新值(如果字段不存在则新增加该列)
db.user.update({name:'张三'},{$set:{age:33}})

# $inc自增字段值
db.user.update({name:'张三'},{$inc:{age:1}})

# $rename修改字段名
db.user.update({name:'张三'},{$rename:{sex:'gender'}})

# $unset删除指定列
db.user.update({name:'张三'},{$unset:{phone:1}})

# setOnInsert当upsert为true时,添加附加字段
db.user.update({name:'赵六'},{$setOnInsert:{age:25,gender:'male'}},{upsert:true})

# 多种赋值表达可以一次执行
db.collection.updae(查询表达式,{
{$set:{...}},
{$unset:{...}},
{$inc:{...}},
{$rename:{...}}
})

2. 修改选项

选项包括upsert和multi

  • upsert:没有匹配的行,是否直接插入该行,默认为false。
  • multi:查询表达式匹配中多行,是否修改多行,默认false(只修改一行)
# 示例
db.user.update({name:'李四'},{$set:{age:44}},{upsert:true})
db.user.update({gender:'male'},{$set:{age:55}},{multi:true})

3.5. query查询

# 语法:db.collection.find(查询表达式,查询的列)
db.user.find() # 查询所有

# 查询匹配条件的所有列
db.user.find({name:'张三'})

# 查询匹配条件的指定列({列名:1,列名:1,...})
db.user.find({name:'张三'},{age:1})

# 不查询id列
db.user.find({name:'张三'},{_id:0,age:1})

1. 字段值查询

# 查询主键为32的商品
db.goods.find({goods_id:32})

# 子文档查询(指向子文档的key是字符串)
db.stu.find({'score.yuwen':75})

# 数组元素查询(指向子文档的key是字符串)
db.stu.find({'hobby.2':'football'})

2. 范围查询

# $ne 不等于
# 查询不属第3栏目的所有商品
db.goods.find({cat_id:{$ne:3}})

# $gt 大于
# 查询高于3000元的商品
db.goods.find({shop_price:{$gt:3000}})

# $gte 大于等于
# 查询高于或等于3000元的商品
db.goods.find({shop_price:{$gte: 3000}})

# $lt 小于
# 查询低于500元的商品
db.goods.find({shop_price:{$lt:500}})

# $lte 小于等于
# 查询低于500元的商品
db.goods.find({shop_price:{$lte:500}})

3. 集合查询

# $in 在集合,(当查询字段是数组时,不需完全匹配也会命中该行)
# 查询栏目为4和11的商品
db.goods.find({cat_id:{$in:[4,11]}})

# $nin 不在集合
# 查询栏目不是3和4的商品
db.goods.find({cat_id:{$nin:[3,4]}})

# $all完全匹配,(当查询字段是数组时,必须完全匹配才命中该行)
db.goods.find({cat_id:{$all:[4,11]}})

4. 逻辑查询

# $and 逻辑与,必须都满足条件
# 查询价格为100到500的商品
db.goods.find({$and:[{shop_price:{$gt:100}},{shop_price:{$lt:500}}]})

# $or 逻辑或,至少满足一个条件
# 查询价格小于100或大于3000的商品
db.goods.find({$or:[{shop_price:{$lt:100}},{shop_price:{$gt:3000}}]})

# $nor 与非逻辑
# 查询不在栏目3,并且价格不小1000的商品
db.goods.find({$nor:[{cat_id:3},{shop_price:{$lt:1000}}]})

5. 元素运算符查询

# $mod 求余
# 查询年龄对10求余为0的用户
db.goods.find({age:{$mod:[10,0]}})

# $exist 查询列是否存在
# 查询有电话属性的用户
db.user.find({phone:{$exists:1}})

# $type 查询属性为指定类型的文档
# 查询为浮点型的文档
db.user.find({phone:{$type:1}})

# 查询为字符串型的文档
db.user.find({phone:{$type:2}})

6. 其他常用查询

# 统计行数
db.goods.count()
db.goods.find({cat_id:3}).count()

# 查询每页数据
    # 按指定属性排序,1表示升序,-1表示降序
    sort({属性:1|-1})
    # 跳过行数
    skip(num)
    # 限制取多少行
    limit(num)

# 页码page,每页行数n,则skip数=(page-1)*n
db.goods.find({cat_id:3}).sort({shop_price:-1}).skip(0).limit(10)

4.索引

索引提高查询速度,降低写入速度,权衡常用的查询字段,不建议在太多列上建索引。在mongodb中,索引可以按字段升序/降序来创建,便于排序。默认是用btree来组织索引文件,也允许建立hash索引。

# 在test库下stu下创建10000行数据的成绩表
for (var i=1;i<=10000;i++){
	db.stu.insert({sn:i,name:'stu'+i,email:'stu'+i+'@126.com',score:{yuwen:i%80,shuxue:i%90,yingyu:i%100}})
}

4.1. 普通索引

1. 单列索引

在表stu创建sn列索引

db.stu.ensureIndex({sn:1})

1表示升序,-1表示降序

2. 多列索引

在表stu创建sn列和name列共同索引

db.stu.ensureIndex({sn:1,name:1})

1表示升序,-1表示降序

3. 子文档索引

在表stu的score列下的yuwen字段创建索引

db.stu.ensureIndex({‘score.yuwen’:1})

1表示升序,-1表示降序

4.2. 唯一索引

创建唯一索引后字段值都是唯一的

在表stu创建email列索引

db.stu.ensureIndex({email:1},{unique:true})

4.3. 稀疏索引

稀疏索引的特点:如果针对field做索引,针对不含field列的文档,将不建立索引。与之相对的普通索引会把该文档的field列的值认为NULL,并建索引。

使用场景:小部分文档含有某列时。

在表stu创建phone列稀疏索引

db.stu.ensureIndex({age:1},{sparse:true})

4.4. 哈希索引

哈希索引速度比普通索引快,缺点是不能对范围查询进行优化。使用场景:随机性强的散列

在表stu创建email列哈希索引

db.stu.ensureIndex({email:‘hashed’})

4.5. 重建索引

一个表经过很多次修改后,导致表的文件产生空洞,索引文件也如此。可以通过索引的重建,减少索引文件碎片,并提高索引的效率,类似mysql中的optimize table

在表stu重建索引

db.stu.reIndex()

4.6. 删除索引

# 语法
db.collection.dropIndex({filed:1/-1});

# 示例
db.stu.dropIndex({sn:1})
db.stu.dropIndex ({email:'hashed'})

4.7. 查看索引和执行计划

# 查看表索引
db.stu.getIndexes()

# 查看执行计划
db.stu.find({sn:5555}).explain() # 默认只输出queryPlanner

# 其中explain()参数有三个,分别是'queryPlanner'、'executionStats'、'allPlansExecution'
db.stu.find({sn:5555}).explain('executionStats')

# explain分析结果的几个重要字段,通过结果分析可以判断是否需要优化执行语句

executionStats属性下的字段:

  • executionTimeMillis:查询耗时,单位(ms)
  • totalDocsExamined:扫描文档数
  • executionStages.stage:”COLLSCAN”表示全表扫描,”FETCH”表示索引扫描
  • executionStages. executionTimeMillisEstimate:索引扫描耗时,单位(ms)

winningPlan.inputStage属性下的字段:

  • indexName:索引名字

5.MongoDB的账号管理

在mongodb中有一个admin数据库,牵涉到服务器配置层面的操作,需要先切换到admin数据库,use admin命令相当于进入超级用户管理模式。

mongo的用户是以数据库为单位来建立的,每个数据库有自己的管理员。

我们在设置用户时,需要先在admin数据库下建立管理员,这个管理员登陆后,相当于超级管理员,然后可以切换到其他库,添加普通用户。

注意: mongodb服务器启动时,默认是不需要认证的,要让用户生效,需要启动服务器时指定–auth选项。添加用户后,我们再次退出并登陆,认证才有效。

5.1. 创建管理员

# (1)创建用户管理员(在管理身份验证数据库)。
use admin
db.createUser(
  {
    user: "admin",
    pwd: "xxx",
    roles: [{role: "userAdminAnyDatabase", db: "admin"}]
  }
)

# (2)重新启动MongoDB实例与访问控制。
mongod --dbpath /data/mongodb/database --logpath /data/mongodb/log/mongodb.log --port 27017 --fork --auth

# (3)连接和用户管理员进行身份验证。
mongo --port 27017 -u "krislin" -p "xxx" --authenticationDatabase "admin"

5.2. 创建自定义用户

# (1) 给其他数据库test配置一个读写权限的用户
use test
db.createUser(
  {
    user: "myTester",
    pwd: "xyz123",
    roles: [ { role: "readWrite", db: "test" },
             { role: "read", db: "reporting" } ]
  }
)

# (2)mytest连接和验证。
mongo --port 27017 -u "myTester" -p "xyz123" --authenticationDatabase "test"
# 或登录后执行命令验证
use test
db.auth("myTester","xyz123")

5.3. 查看已经创建的用户

# 查看创建的用户需要在管理员数据库上执行
use admin
db.system.users.find()

# 查看当前数据库用户
show users

5.4. 删除用户

# 删除一个用户
use dbname
db.system.users.remove({user:"username"})

# 删除管理员
use admin
db.system.users.remove({user:"admin"})

6.其他操作

6.1. 获取MongoDB状态信息

首先在admin下创建一个新能够获取mongodb状态权限的用户

use admin
db.createUser(
  {
    user: "stat",
    pwd: "123456",
    roles: [{role: "mongostatRole", db: "admin"}]
  }
)

每隔2秒采集一次信息保存到文件stat.log

mongostat -u stat -p 123456 –authenticationDatabase admin -n 2 –json >> stat.log

每一条统计信息如下:

JSON{
    "localhost:27017":{
        "arw":"1|0",
        "command":"2|0",
        "conn":"4",
        "delete":"*0",
        "dirty":"0.0%",
        "flushes":"0",
        "getmore":"0",
        "insert":"*0",
        "net_in":"18.9k",
        "net_out":"79.0k",
        "qrw":"0|0",
        "query":"94",
        "res":"49.0M",
        "time":"14:41:32",
        "update":"*0",
        "used":"0.1%",
        "vsize":"938M"
    }
}

更多mongostat命令说明看官网 https://docs.mongodb.com/manual/reference/program/mongostat/

6.2. 非正常关闭MongoDB导致无法启动的解决方法

非正常关闭包括断电或强制关闭,造成文件mongod.lock锁住了,所以无法正常启动,解决方法:

(1) 删除mongod.lock文件,文件存放一般在数据库文件夹里
rm /data/mongodb/db/mongod.lock

(2) repair的模式启动
mongod -f /usr/local/mongodb/mongodb.conf –repair

(3) 启动mongodb
mongod -f /usr/local/mongodb/mongodb.conf
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值