MongoDB 的使用

MongoDB 的使用

mongoDB 的常见命令使用;MongoDB默认在 27017 端口上运行;

1.常见命令

# 进入交互终端
mongo 

开启云监控平台

// 开启云监控平台[公司一般不会允许内部信息泄露,所以不会开启这个功能]
db.enableFreeMonitoring()
// 关闭云监控平台
db.disableFreeMonitoring()

image-20221015113918405

在浏览器中输入产生的url

image-20221015114022527

云监控平台就会被加载出来;

成功运行了mongoDB以后,对于mongodmongo的区别

mongod是处理MongoDB系统的主要进程。主要负责处理数据请求,管理数据存储,和执行后台管理操作。当我们运行mongod命令意味着正在启动MongoDB进程, 并且在后台运行。

mongo是一个命令行实现的客户端操作mongodb的工具,用于连接一个特定的mongod实例。当我们没有带参数运行mongo命令它将使用默认的localhost:27017和mongod进行连接。

# 退出交互终端;两条命令都可以直接退出交互终端;
exit
quit() 

查看版本

mongo --version 
# 或者终端内部使用 version()

交互终端使用帮助命令

>db.help()
db.help()                    help on db methods   查看操作数据的方法
db.mycoll.help()             help on collection methods  查看集合的操作方法
sh.help()                    sharding helpers  查看分片集share的帮助信息
rs.help()                    replica set helpers 查看复制集的帮助信息
help admin                   administrative help 查看管理的操作帮助信息
help connect                 connecting to a db help
help keys                    key shortcuts
help misc                    misc things to know
help mr                      mapreduce

show dbs                     show database names  查看当前系统所有的数据库
show collections             show collections in current database 查看当前数据库所有的数据集合
show users                   show users in current database  查看当前数据库中所有的管理员用户
show profile                 show most recent system.profile entries with time >= 1ms
show logs                    show the accessible logger names 查看全部日志
show log [name]              prints out the last segment of log in memory, 'global' is default                          查看指定日志信息
use <db_name>                set current database   切换操作的数据库
db.mycoll.find()             list objects in collection mycoll  列出当前指定集合下的所有文档
db.mycoll.find( { a : 1 } )  list objects in mycoll where a == 1 按条件查询指定集合下所有文档
it                           result of the last line evaluated; use to further iterate
查看更多的查询结果,相当于下一页
DBQuery.shellBatchSize = x   set default number of items to display on shell
修改返回结果数据的单页显示数量,默认20条
exit                         quit the mongo shell  退出终端
  • 查看当前服务器状态

    db.serverStatus()
    # 效果:
    {
    	"host" : "ubuntu",    # 主机名
    	"version" : "4.4.2",  # mongodb版本
    	"process" : "mongod", # mongodb进程,主要有mongod和mongos(分片集群中)两种
    	"pid" : NumberLong(1034),  # mongod的pid进程号,可以在linux终端下使用命令 pidof mongod 验证
    	"uptime" : 105063,    # mongod服务启动的秒数
    	"uptimeMillis" : NumberLong(105063193), # mongod服务启动的毫秒数
    	"uptimeEstimate" : NumberLong(105063),  # mongod内部自己计算的启动秒数
    	"localTime" : ISODate("2020-12-08T16:01:08.230Z"), # 本地时间,相当于 python的 datetime
    	# 连接数相关 
    	"connections" : {
    		"current" : 1,  # 当前连接数
    		"available" : 51199, # 可用最大连接数
    		"totalCreated" : 1,  # 截止目前为止总共创建的连接数
    		"active" : 1,   # 还在活跃的连接数
    	},
    
    	"globalLock" : {  # 全局锁相关信息
    		"totalTime" : NumberLong("105063115000"), # mongod启动后到现在的总时间,单位微秒
    		"currentQueue" : { # 当前等待锁队列
    			"total" : 0,   # 当前全局锁的等待个数
    			"readers" : 0, # 当前全局读锁等待个数
    			"writers" : 0  # 当前全局写锁等待个数
    		},
    		"activeClients" : {
    			"total" : 0,   # 当前活跃客户端的个数
    			"readers" : 0, # 当前活跃客户端中进行读操作的个数
    			"writers" : 0  # 当前活跃客户端中进行写操作的个数
    		}
    	},
    
    	"network" : { # 网络相关
    		"bytesIn" : NumberLong(1611),    # 数据库接收到的网络传输字节数
    		"bytesOut" : NumberLong(51269),  # 从数据库发送出去的网络传输字节数
    		"numRequests" : NumberLong(16),  # mongod接收到的总请求次数
    	},
    	
    	# 操作计数器
    	"opcounters" : {
    		"insert" : NumberLong(0),  # 本次mongod实例启动至今收到的插入操作总数 
    		"query" : NumberLong(287), # 本次mongod实例启动至今收到的查询总数。
    		"update" : NumberLong(0),  # 本次mongod实例启动至今收到的更新操作总数 。
    		"delete" : NumberLong(0),  # 本次mongod实例启动至今的删除操作总数。
    		"getmore" : NumberLong(0), # 本次mongod实例启动至今“getmore”操作的总数。
    		"command" : NumberLong(588)# 本次mongod实例启动至今向数据库发出的命令总数 。
    	},
    
    	# 存储引擎,是MongoDB的核心组件,负责管理数据如何存储在硬盘(Disk)和内存(Memory)上
    	# MongoDB 支持多种不同的存储引擎(Storage Engine),MongoDB支持的存储引擎有:WiredTiger,MMAPv1和In-Memory。
    	# 1. WiredTiger,将数据持久化存储在硬盘文件中;从MongoDB 3.2 版本开始,成为MongDB默认存储引擎
    	# 2. In-Memory,将数据存储在内存中
    	# 3. MMAPv1,将数据持久化存储在硬盘文件中; MongoDB 3.2 版本以前的默认存储引擎
    	
    	# WiredTiger是比MMAPv1更好用,更强大的存储引擎,WiredTiger的写操作会先写入缓存(Cache)中,并持久化到WAL(Write ahead log,写日志),每60s或日志文件达到2GB时会做一次Checkpoint(检查点),将当前数据进行持久化,产生一个新的快照。Wiredtiger连接初始化时,首先将数据恢复至最新的快照状态,然后根据WAL恢复数据,以保证存储可靠性。
    	# Checkpoint,检测点。将内存中的数据变更冲刷到磁盘中的数据文件中,并做一个标记点。
    	#             表示此前的数据表示已经持久存储在了数据文件中,此后的数据变更存在于内存和日志中.
    	#             是一种让数据库redo(重做)和data(数据)文件保持一致的机制。
    	#             并非Mongodb独有的,mysql中的InnoDB也有。
    
    	"storageEngine" : {
    		"name" : "wiredTiger", 
    		"supportsCommittedReads" : true,
    		"oldestRequiredTimestampForCrashRecovery" : Timestamp(0, 0),
    		"supportsPendingDrops" : true,
    		"dropPendingIdents" : NumberLong(0),
    		"supportsTwoPhaseIndexBuild" : true,
    		"supportsSnapshotReadConcern" : true,
    		"readOnly" : false,
    		"persistent" : true,
    		"backupCursorOpen" : false
    	},
    	
    
    	"transactions" : { # 多文档事务,mongodb4.0以后新增特性
    		"retriedCommandsCount" : NumberLong(0),
    		"retriedStatementsCount" : NumberLong(0),
    		"transactionsCollectionWriteCount" : NumberLong(0),
    		"currentActive" : NumberLong(0),
    		"currentInactive" : NumberLong(0),
    		"currentOpen" : NumberLong(0),
    		"totalAborted" : NumberLong(0),
    		"totalCommitted" : NumberLong(0),
    		"totalStarted" : NumberLong(0),
    		"totalPrepared" : NumberLong(0),
    		"totalPreparedThenCommitted" : NumberLong(0),
    		"totalPreparedThenAborted" : NumberLong(0),
    		"currentPrepared" : NumberLong(0)
    	},
    	"locks":{ # 锁相关
    	
    	},
    	"mem" : { # 内存相关
    		"bits" : 64, # 操作系统位数
    		"resident" : 18,  # 物理内存消耗,单位:M
    		"virtual" : 1566, # 虚拟内存消耗
    		"supported" : true # 是否显示额外的内存信息
    	},
    }
    
  • 查看主机地址

    > db.getMongo()
    connection to 127.0.0.1:27017
    
  • 查看日志

    show logs
    // global
    // startupWarnings
    
    // 如果要查看具体文件的日志。
    show log global   
    // global是全局日志,默认保存的日志文件在 /var/log/mongodb/mongod.log
    // 如果mongoDB无法启动,查看错误就可以来到默认日志文件查看
    

    image-20221015114924635

2.数据备份与恢复

MongoDB 一共提供了 4 个命令行工具给我门对数据进行备份与恢复以及导入导出数据;

备份与恢复操作的数据文件格式是json格式,二进制

准备测试数据,MongoDB 的终端进行一下操作;

use demo
fotmatnumber = (start, end)=>{
    num = Math.round(Math.random() * (end-start)) + start
    if(num<10){
        return "0"+num;
    }else{
        return num;
    }
}

rand_title = (i)=>{
    num = Math.round( Math.random() * 10 );
    num1 = Math.round( Math.random() * 10 );
    return [
        "赠送礼品-"+num,
        "购物狂欢-"+num,
        "随便买买-"+num,
        "愉快购物-"+num,
        "赠送礼物-"+num,
        "商品购买-"+num,
        "买多送多-"+num,
        "买年货-"+num,
        "买买买买-"+num,
        "充值会员-"+num
    ][num1];
}

for(var i=0; i<200000; i++){  
    db.orders.insert({
        "onumber": ( "0000000000000000" + i ).substr( String(i).length ),  
        "date": "20"+fotmatnumber(0,21)+"-"+fotmatnumber(1,12)+"-"+fotmatnumber(1,31),  
        "title": rand_title(i),
        "user_id": parseInt(i/200)+1,
        "items" :[{ 
        	"goods_id" : parseInt(i/200)+1,
        	"goods_attr" : i,  
        	"price" : 100.0
        },{ 
        	"goods_id" : parseInt(i/200)+2,
        	"goods_attr" : i+1,  
        	"price" : 80.0
        }]
    })
    if(i%10000==0){
        print("已经添加了"+parseInt(i/10000)+"万条数据!");
    }
}

导入与导出数据文件格式是 json 格式,文本格式

提醒:执行导入导出命令的时候是在终端执行的,并不是在交互终端执行,与mysql相似;

  • 数据备份

    mongodump -h dbhost -d dbname -o dbdirectory
    mongodump -h 地址 -d 数据库的名字 -o 保存的目录(路径)
    // 语法如上,示例如下
    mongodump -h 127.0.0.1 -d demo -o /home/backup
    

    参数说明

    选项作用备注
    -hMongoDB服务端地址和端口的简写–host=MongoDB地址 --port=端口
    -d备份的数据库名称–db=数据库名称
    -o备份数据保存目录目录需要提前创建
  • 数据备份

    mongorestore -h dbhost -d dbname --dir dbdirectory --drop
    # 例如:恢复上面备份的demo数据库
    mongorestore -h 127.0.0.1:27017 -d demo --dir /home/backup
    

    参数说明:

    选项作用备注
    -hMongoDB服务端地址和端口的简写–host=MongoDB地址 --port=端口
    -d备份的数据库名称–db=数据库名称
    –dir备份数据所在目录
    –drop恢复数据前,先删除MongoDB中的旧数据
  • 数据导出

    mongoexport -d dbname -c collectionname -o file --type json/csv -f field
    # 例如:导出demo数据库的orders集合数据
    mongoexport -d demo -c orders -o /home/moluo/Desktop/backup/orders.json --type json
    

    参数说明:

    选项作用备注
    -d要导出的数据库名称–db=数据库名称
    -c要导出的集合名称–collection=集合名称
    -o导出数据保存的文件名
    –type导出数据的文件格式默认是json,也可以是csv,当数据格式为csv时,
    另需加上-f “字段1,字段2,…”
  • 数据导入

    mongoimport -d dbname -c collectionname --file filename --headerline --type json/csv -f field
    # 例如:把上面导出的json中的数据,导入到demo数据库的orders集合中
    mongoimport -d demo -c orders --file /home/.../orders.json --type json
    

    参数说明

    选项作用备注
    -d要导入的数据库名称–db=数据库名称
    -c要导入的集合名称–collection=集合名称
    –file导入数据保存的文件名
    –type导入数据的文件格式默认是json,也可以是csv 当数据格式为csv时:
    1. 需加上-f “字段1,字段2,…”
    2. 可以选择加上–headerline,设置首行为导入字段

3.用户管理

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

管理员可以查看自己的数据库,但是你能直接管理其他的数据库,要先在内置的数据库 admin 认证后才可以.

管理员的权限设置包含了 2块,分别是角色和权限,由创建用户是通过roles属性进行设置。

3.1 创建用户

db.createUser(user,pwd,writeConcern)

创建一个数据库新用户用db.createUser()方法,如果用户存在则返回一个用户重复错误.

错误信息:uncaught exception: Error: couldn't add user: User "用户名@数据库" already exists

语法:

{
    user: "<用户名>",
    pwd: "<密码>",
	customData: { <any information> }, // 任意内容,主要是为了表示用户身份的相关介绍 
	roles: [ // 角色和权限分配
		{ role: "<role>", db: "<database>" },  // 也可以直接填写由mongoDB内置的角色,例如: "<role>"
		...
    ]
}

3.2 权限管理

mongo 中存在内置的角色

数据库用户角色:read、readWrite; 
数据库管理角色:dbAdmin、dbOwner、userAdmin;
集群管理角色:clusterAdmin、clusterManager、clusterMonitor、hostManager; 
备份恢复角色:backup、restore; 
所有数据库角色:readAnyDatabase、readWriteAnyDatabase、userAdminAnyDatabase、dbAdminAnyDatabase 
超级用户角色:root
// 有几个角色间接或直接提供了系统超级用户的访问权限(dbOwner 、userAdmin、userAdminAnyDatabase)

mongo 中的内置权限

Read:允许用户读取指定数据库
readWrite:允许用户读写指定数据库
dbAdmin:允许用户在指定数据库中执行管理函数.索引创建、删除,查看统计或访问system.profile
userAdmin:允许用户向system.users集合写入,可以找指定数据库里创建、删除和管理用户
clusterAdmin:只在admin数据库中可用,赋予用户所有分片和复制集相关函数的管理权限。
readAnyDatabase:只在admin数据库中可用,赋予用户所有数据库的读权限
readWriteAnyDatabase:只在admin数据库中可用,赋予用户所有数据库的读写权限
userAdminAnyDatabase:只在admin数据库中可用,赋予用户所有数据库的userAdmin权限
dbAdminAnyDatabase:只在admin数据库中可用,赋予用户所有数据库的dbAdmin权限。
root:只在admin数据库中可用。超级账号,擁有超级权限

给 admin 数据库创建账户管理员,当前账号只能用于管理 admin 数据库账号,不能进行其他数据库的操作。

// 进入/切换数据库到admin中
use admin;
// 创建账户管理员
// [用户名:admin,密码:123456,数据库:admin,角色userAdminAnyDatabase,表示admin用户在admin数据库中具有超级用户权限]
db.createUser({
	user: "admin",// 用户名
	pwd: "123456",// 密码
	roles: [
		{role: "userAdminAnyDatabase",db:"admin"},// 角色
        // userAdminAnyDatabase
	]
});

image-20221015141742110

创建超级管理员,当前账号可以进行数据库相关操作;

// 进入/切换数据库到admin中
use admin
// 创建超级管理员账号
db.createUser({
    user: "root",
    pwd: "123456",
    roles: [
    	{role:"root", db:"admin"},  // 也可以这样简写:"root",
    ]
})

image-20221015142300066

3.3 创建用户自己的数据库的角色

账号是跟着数据库绑定的,所以是什么数据库的用户,就鼻血在指定库里授权和验证!!!

一般开发中,往往是一个项目就分配一个数据库,并给这个数据库分配一个管理员!!!

补充:

use dbname # 当数据库存在的情况下会直接切换到指定的数据库中,不存在则创建并切换
# 进入某个具体的数据库中 输入 db 会输出数据库的名字

image-20221015143005157

// 切换数据库,如果当前库不存在则自动创建
use mofang;
// 创建管理员用户,为了保证不会报错,所以先删除同名管理员 db.system.users.remove({user:"mofang"});
db.createUser({
    user: "mofang",
    pwd: "123456",
    roles: [
        { role: "dbOwner", db: "mofang"}
    ]
})

image-20221015143306783

查看当前数据库下的用户

> show users
{
	"_id" : "mofang.mofang",
	"userId" : UUID("772bf3a8-47e1-424e-8788-501a3e2ff867"),
	"user" : "mofang",
	"db" : "mofang",
	"roles" : [
		{
			"role" : "dbOwner",
			"db" : "mofang"
		}
	],
	"mechanisms" : [
		"SCRAM-SHA-1",
		"SCRAM-SHA-256"
	]
}

3.4 用户信息

查看当前数据库下的管理用户,只需要切换到对应的库中即可查看

use mofang
show users

查看系统中所有的用户,需要切换到admin中使用账号管理员的权限进行操作

use admin
// db.auth("root","123456") // 如果开启了mongoDB的访问控制,就需要下用户认证密码才能继续往下操作
db.system.users.find() // 只能在admin数据库中使用。
db.system.users.find().pretty()  // pretty表示在返回多个查询结果时,以结构化格式显示数据

image-20221015143749310

image-20221015143807507

3.5 删除用户

db.system.users.remove(json条件)

// 有多种删除方式,下面是根据user用户名删除用户
use admin
db.system.users.remove({user:"mofang"});

// 删除效果:
WriteResult({ "nRemoved" : 1 })  // nRemoved 大于0表示成功删除管理员,等于0则表示没有删除。

3.6 修改密码

必须切换到对应数据库下才能给用户修改密码;

db.changeUserPassword("账户名", "新密码")

mongo终端操作:

use mofang
// 注册必须保证有这个管理员
db.changeUserPassword("mofang", "123")

3.7 开启账户认证

sudo vim /etc/mongod.conf
// 找到31行附近的 security,去掉左边注释符号(#)
security:
    authorization: enabled

:wq
// 重启mongdb,配置生效
sudo systemctl restart mongod

// 开启了账户认证机制以后,再次进入mofang
mongo
use mofang
show users    // 此处会报错如:uncaught exception: Error: command usersInfo requires authentication
db.auth("mofang","123")   // 此处认证时填写错误密码,报错如下:
// Error: Authentication failed.
// 0
exit
mongo
db.auth("mofang","123456")  // 此处认证时填写正确密码,效果如下:
// 1
show users    // 此时经过认证以后,当前命令就不会被限制了。 

image-20221016104456485

4. 库管理

  • 显示所有数据库列表【空数据库不会显示,或者说空数据库已经被 MongoDB 回收了.】

    # 两条命令都可以显示数据库的列表信息;
    show dbs
    show databases
    

    image-20221015154731975

  • 切换数据库,如果数据库不存在则创建数据库。

    use  <database>
    
  • 删除当前数据库,如果数据库不存在也会返回{"ok":1}

    use <db>          // 先切换到要删除的数据库中,然后才能删除数据库
    db.dropDatabase()
    

    image-20221015155118083

  • 查看当前数据库状态

    > db.stats()
    {
    	"db" : "mofang",
    	"collections" : 0,
    	"views" : 0,
    	"objects" : 0,
    	"avgObjSize" : 0,
    	"dataSize" : 0,
    	"storageSize" : 0,
    	"totalSize" : 0,
    	"indexes" : 0,
    	"indexSize" : 0,
    	"scaleFactor" : 1,
    	"fileSize" : 0,
    	"fsUsedSize" : 0,
    	"fsTotalSize" : 0,
    	"ok" : 1
    }
    

在 mongoDB 中,最重要的核心文档,如果一个库或者一个库下的集合中的文档全部被删除了,则这个库和这个集合就会 mongoDB 回收删除

5.集合管理

在 MongoDB 中其实不需要专门创建集合,直接添加文档,MongoDB 也会自动生成集合。

5.1 集合的创建

// name为必填参数,options为可选参数。capped若设置值为true,则size必须也一并设置
db.createCollection(
	name=<集合名称>, 
	options  = { 
		capped : <boolean>,       // 创建固定集,固定集指限制固定数据大小的集合,当数据达到最大值会自动覆盖最早的文档内容
		size : <bytes_size>,      // 指定固定集合存储的最大字节数,单位:字节数.
		max : <collection_size>   // 指定固定集合中包含文档的最大数量,单位:字节数
});

// 添加文档到不存在的集合中,mongodb会自动创建集合,
// db.<集合名称>.insert({"name":"python入门","price" : 31.4})
db.courses.insert({"name":"python入门","price" : 31.4})

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OPzCtNyO-1670162213826)(…/…/typoraImage/image-20221015160309648.png)]

# 集合列表
show collections 
show tables

5.2 删除集合

db.集合.drop()

5.3 查看集合

db.getCollection("集合")
db.集合

查看集合创建信息

db.printCollectionStats()

6.文档管理

文档相当于数据库中的行例,具体数据;

MongoDB 中,文档也叫 object/document.

数据类型

Type描述
ObjectID用于存储问文档的ID,相当于主键,区分文档的唯一字段,
MongoDB中就是一个对象的返回值
String字符串是最常用的数据类型,MongoDB 中的字符串必须是 UTF-8 编码。
Integer整数用于存储数值,可以是32位也可以是64位,取决于服务器。
Double双精度数据类型,存储浮点值
Boolean存储布尔类型,true/false
Arrays将数组、列表或多个值存储到一个键,[]
Timestamp时间戳,用于记录文档何时被修改或创建。Date(),Timestamp(),ISODate()
Object用于嵌入文档,相当于子属性是另一个json文档而已,这种方式就可以实现嵌套[]
Null空值,相当于 Python 的 None
Symbol与字符串用法相同,常用于某些使用特殊符号的语言,二进制
Date用于以UNIX时间格式存储当前日期或时间。
Binary data二进制数据,常用于保存文件的内容,往往是图片,数据本身。
Code用于将JavaScript代码存储到文档中
Regular expression正则表达式

6.1 添加文档

文档的数据结构和json基本一样,所有存储在集合中的数据内部存储的格式都是 BSON 格式。

BSON 是一种类似 json 的二进制形式的存储格式,是Binary Json的简称。

// 添加文档
// 方式1:
db.<集合名称>.insert(<document>)  // document就是一个json格式的数据

// 方式2
db.<集合名称>.insertOne(          // 如果文档存在_id主键为更新数据,否则就添加数据。
   <document>
)

// 方式3:
// 一次性添加多个文档, 多次给同一个集合建议使用insertMany比insertOne效率更好
db.<集合名称>.insertMany([
    <document>,
    <document>,
    ...
])

image-20221015204214671

补充:mongo 原则上内置了 js 解释引擎,所以支持 js 语法。

// 添加一条数据
db.user_list.insert({"name":"laoli","age":33,"sex":true,"child": {"name":"xiaohuihui","age":3}});
// WriteResult({ "nInserted" : 1 })

/*
// mongo原则上内置了js解释引擎,所以支持js语法
> db.user_list.find()[0]._id
ObjectId("61552b913ccd8ec29dbf6512")
> db.user_list.find()[0].name
laoli

image-20221015204741863

通过 javascript 的typeof 来查看数据的类型;

// javascrit总可以通过typeof 来查看数据的类型
> typeof db.user_list.find()[0].name
string
> typeof db.user_list.find()[0]._id
object
> typeof db.user_list.find()[0].sex
boolean
> typeof db.user_list.find()[0].age
number
> typeof db.user_list.find()[0].child
object
> typeof db.user_list.find()[0].child.name
string
*/
  • 其他添加数据的方法

    // 添加一条数据
    db.user_list.insertOne({"name":"xiaozhang","age":18,"sex":true});
    // {
    // 	"acknowledged" : true,
    // 	"insertedId" : ObjectId("605021e6d5c7a55cc95c1cb7")
    // }
    

    image-20221015205834156

    // 添加多条数据
    document1 = {"name":"xiaolan","age":16}
    document2 = {"name":"xiaoguang","age":16}
    db.user_list.insertMany([document1,document2]);
    

    image-20221015210021296

查看添加好的数据

// 相关命令
db.<集合名称>.find()

image-20221015210209665

6.2 删除文档

  • 方式一

    // 方式1
    db.<集合名称>.remove(
       <query>,  // removed的条件,一般写法:{"属性":{条件:值}},如果不填写条件,删除所有文档
       {
         justOne: <boolean>,      // 可选删除,是否只删除查询到的第一个文档,默认为false,删除所有
         writeConcern: <document> // 可选参数,抛出异常的级别。
       }
    )
    // 删除满足条件的第一条数据
    // 条件 {"age":{$eq:16}}   相当于 age == 16
    // db.user_list.remove({"age":{$eq:16}},{"justOne":true})
    // 删除满足条件的所有数据,条件中$wq可以不写
    // db.user_list.remove({"age":16}); // 等于可以省略不写,相当于 db.user_list.remove({"age":{$eq:16}});
    

    image-20221015210545360

  • 方式二,删除一条数据

    db.<集合名称>.deleteOne(
       <query>,  // removed的条件,一般写法:{"属性":{条件:值}},如果不填写条件,删除所有文档
       {
         justOne: <boolean>,      // 可选删除,是否只删除查询到的第一个文档,默认为false,删除所有
         writeConcern: <document> // 可选参数,抛出异常的级别。
       }
    )
    
    

    image-20221015210841227

  • 方式三,删除多条

    // 方式3:删除多条数据
    db.<集合名称>.deleteMany(
       <query>,  // removed的条件,一般写法:{"属性":{条件:值}},如果不填写条件,删除所有文档
       {
         justOne: <boolean>,      // 可选删除,是否只删除查询到的第一个文档,默认为false,删除所有
         writeConcern: <document> // 可选参数,抛出异常的级别。
       }
    )
    

    image-20221015211101862

方式二 和 方式三结合使用,可以使得方式一的条件变得简单;

6.3 查询文档

  • 直接显示查询的所有,find 和 findOne 的第二个参数,也是一个 json 对象,一般称之为字段投影表示设置是否显示或隐藏指定数据字段。

  • 获取一条

    db.集合.findOne(
    	<query>,     // 查询条件,删除、查询、修改都需要条件、条件写法基本一样的。
        {
        	<key>: 0, // 隐藏指定字段,例如:"_id":0,
        	<key>: 1, // 显示指定字段,例如:"title":1,
        	....
        }
    )
    

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CSxVrgPi-1670162213841)(…/…/typoraImage/image-20221015211936182.png)]

    通过观察,可以得出,当筛选的条件不存在的时候,返回的是 null;

  • 获取多条

    db.集合.find()
    

    image-20221015215616044

  • 以易读的方式来格式化显示读取到的数据,只能 find 方法后面使用。

    db.集合.find().pretty()
    

    image-20221015220038142

  • 操作集合

    // 切换数据库
    use mofang;
    
    // 添加测试数据
    docs = [
        {"name":"xiaohuang","sex":0,"age":15,"mobile":"13301234568"},
        {"name":"xiaofei","sex":1,"age":16,"mobile":"1351234568"},
        {"name":"xiaolong","sex":1,"age":19,"mobile":"15001234568"},
        {"name":"xiaomianyang","sex":0,"age":13,"mobile":"15001234568"}
    ]
    db.user_list.insertMany(docs);
    
    // 查询一条数据
    db.user_list.findOne()    // 获取集合中第一条数据
    db.user_list.findOne({})  // 同上
    db.user_list.findOne({},{_id:0,child:0})    // 获取集合中第一条数据,并隐藏_id 和 child属性的数据
    db.user_list.findOne({},{_id:0,name:1,mobile:1})  // 获取集合中第一条数据,只查询文档的name和mobile属性的数据
    db.user_list.findOne({name:"xiaocao"},{_id:0,name:1,mobile:1})
    db.user_list.findOne({name:"xiaoming", age:18})
    
    // 查询多条数据
    db.user_list.find()
    db.user_list.find().pretty()
    db.user_list.find({sex:1})
    db.user_list.find({sex:0},{_id:0,name:1,mobile:1})
    
  • 条件运算符【查询器】

    • 比较运算

      格式语法例子SQL中的类似语句
      等于{<key>:<val>} {<key>:{$eq:<val>}}db.集合.find({"name":"xiaoming"})where name = 'xiaoming'
      小于{<key>:{$lt:<val>}}db.集合.find({"age":{$lt:17}})where age < 17
      小于或等于{<key>:{$lte:<val>}}db.集合.find({"age":{$lte:17}})where age <= 17
      大于{<key>:{$gt:<val>}}db.集合.find({"age":{$gt:17}})where age > 17
      大于或等于{<key>:{$gte:<val>}}db.集合.find({"age":{$gte:17}})where age >= 17
      不等于{<key>:{$ne:<val>}}db.集合.find({"age":{$ne:17}})where age != 17
      包含{<key>:{$in:[<val>...]}}db.集合.find({"age":{$in:[1,2,3]}})where age in (1,2,3)
      db.user_list.find({"age":{$lte:18}})// 年龄小于等于 18
      db.user_list.find({"age":{$gte:18}}) // 大于等于 18
      db.user_list.find({"age":{$in:[16,33,13]}})// 指定包包含值
      
      // 添加测试数据
      db.user_list.insert({"name":"laowang","age":32,"sex":true,"child": {"name":"xiaowang","age":4}});
      db.user_list.insert({"name":"laozhang","age":33,"sex":true,"child": {"name":"xiaozhang","age":5}});
      db.user_list.find({"child.age":{$gt:3}})
      db.user_list.find({"child.age":{$in:[3,5]}})
      

      image-20221015221537366

      image-20221015221906272

    • 逻辑运算

      操作语法语法例子
      $and{<key>:<val>,<key>:<val>,...} {$and: [{key:{$运算符:<val>}},....]}db.集合.find({key1:value1, key2:value2})
      $or{$or: [{<key>: {$运算符:<val>}}, ....]}db.集合.find({$or: [{key1: value1}, {key2:value2}]})
      $and$or{<key>:<val>, $or: [{<key>: {<$运算符>:<val>}},...]} {$and:[{$or:[{<key>:{<$运算符>:<val>}},..]},$or:[{<key>:{<$运算符>:<val>}},..]}]}db.集合.find({key1:value1, $or: [{key1: value1}, {key2:value2}]})
      $not{<key>:{$not:{<$运算符>:<val>}}}$not操作符不支持``$regex`正则表达式操作
      // 查询age=18 并且 sex=true
      db.user_list.find({
          $and:[
              {"age":{$eq:18}},
              {"sex":{$eq:true}}
          ]
      })
      // 简写:
      db.user_list.find({
          $and:[
              {"age":18},
              {"sex":true}
          ]
      })
      // 继续简写;
      db.user_list.find({ "age":18, "sex":true })
      
      // 查询age=16或者age=18
      db.user_list.find({
          $or:[
              {"age":{$eq:15}},
              {"age":{$eq:18}}
          ]
      })
      
      // 查询年龄!=16的
      db.user_list.find({"age":{$not:{$eq:16}}})
      db.user_list.find({"age":{$ne:16}})
      
      
      // 查询age=33的男生 或者 age=18的男生
      db.user_list.find({
          "sex":true,
          $or:[
              {"age":18},
              {"age":33}
          ]
      });
      
      db.user_list.find({
          "sex":true,
          "age":{
          	$in:[18,33]
       	}
      });
      
      db.user_list.find({
          $or:[
              {$and:[{"sex":true},{"age":18}]},
              {$and:[{"sex":true},{"age":33}]},
          ]
      });
      
      db.user_list.find({
          $or:[
              {"sex":true,"age":18},
              {"sex":true,"age":33},
          ]
      });
      
    • 其他运算符

      操作格式语法例子说明
      $type{<key>:{$type: <datetype>}}db.集合.find({"name":{$type:'string'}})匹配指定键是指定数据类型的文档 number 数值型 string 字符串 bool 布尔类型 object json文档对象类型 array 数组类型
      $exists{<key>:{$exists:<bool>}db.集合.find({"title":{$exists:true}})匹配具有指定键的文档,存在指定字段的文档
      $regex{ <key>:/模式/<修正符>} {<key>:{$regex:/模式/<修正符>}}db.集合.find({"name":{$regex:/张$/}})按正则匹配
      $mod{<key>: {$mod: [除数, 余数]}}db.集合.find({"age":{$mod:[10,0]}})算数运算,取模,语法中举例是age除以10==0
      db.user_list.insert({"name":"xiaoming","sex":0,"age":"18"});
      db.user_list.insert({"name":"xiaoming","sex":1,"age":"18"});
      db.user_list.insert({"name":"xiaoming","sex":1,"age":"33"});
      db.user_list.insert({"name":"xiaoming","sex":0,"age":"33"});
      // $type
      db.user_list.find({"sex":{$type:"number"}});
      db.user_list.find({"age":{$type:"string"}});
      
      
      // $exists
      db.user_list.find({"child":{$exists:true}});
      
      // $regex 正则匹配
      db.user_list.insert({"name":"xiaoming","sex":0,"age":"18","mobile":"13301234568"});
      db.user_list.insert({"name":"xiaoming","sex":1,"age":"18","mobile":"1351234568"});
      db.user_list.insert({"name":"xiaoming","sex":1,"age":"33","mobile":"15001234568"});
      db.user_list.insert({"name":"xiaoming","sex":0,"age":"33","mobile":"15001234568"});
      
      // 符合手机格式
      db.user_list.find({"mobile":{$regex: /1[3-9]\d{9}/ }});
      // 不符合手机号码格式的
      db.user_list.find({"mobile":{$not:{$regex: /1[3-9]\d{9}/ }}});
      
      
      // $mod
      db.user_list.find({"age":{$mod: [3,0] }});
      
    • 自定义条件函数

      提示:该方式慎重使用,效率比较差。

      // 用法1,逻辑比较复杂的情况,可以使用更多的javascript进行运算处理:结果函数结果为true,则当前数据被查询出来。
      db.<集合名称>.find({$where: ()=>{
          return <this.字段> <$运算符> <条件值>;
      }}});
      
      // 用法2,相对没那么复杂的,取函数的返回值作为条件值:
      db.集合.find({$where:"<this.字段> <运算符> <条件值>"});
      // db.集合.find({$where:"this.name=='xiaoming'"});
      

      操作:

      db.user_list.find({$where: ()=>{
          return this.name=="xiaoming" && this.age<30;
      }});
      
      // 把字符串作为代码条件执行,当结果为true,则返回当前符合的数据
      db.user_list.find({$where:"this.name=='xiaoming' && this.age>30"});
      
  • 排序显示

    db.集合.find().sort({<key>:1})  // 升序,默认为升序
    db.集合.find().sort({<key>:-1}) // 倒序, 
    

    终端操作:

    db.user_list.find().sort({age:-1});
    db.user_list.find().sort({age:-1, sex:1});
    

    image-20221015222915614

  • 字段投影

    find()方法默认将返回文档的所有数据,但是可以通过设置find()的第二个参数projection,设置值查询部分数据。

    // 获取一条
    db.集合.findOne(
    	<query>// 查询条件
        {
        	<key>: 0, // 隐藏指定字段,例如:"_id":0,
        	<key>: 1, // 显示指定字段,例如:"title":1,
        	....
        }
    )
    // 获取多条
    db.集合.find(
    	<query>,      // 查询条件
        {
        	<key>: 0, // 隐藏指定字段,例如:"_id":0,
        	<key>: 1, // 显示指定字段,例如:"title":1,
        	....
        }
    )
    

    image-20221015223516035

  • 限制与偏移

    limit 方法用于限制返回结果的数量;

    skip 方法用于设置返回结果的开始位置;

    db.集合.find(...).limit(结果数量).skip(跳过数量)
    
    db.user_list.find({},{"_id":0,"name":1,"age":1}).sort({"age":1}).limit(5);
    db.user_list.find({},{"_id":0,"name":1,"age":1}).sort({"age":1}).limit(5).skip(5);
    

    image-20221015223902565

6.4 更新文档

// 更新数据
db.集合.update(
    <query>,
    <update>,
    {
     upsert: <boolean>, // 可选参数,如果文档不存在,是否插入objNew, true为插入,默认是false,不插入
     multi: <boolean>,  // 可选参数,是否把满足条件的所有数据全部更新,设置更新1条还是多条
     writeConcern: <document> // 可选参数,抛出异常的级别。
   }
)

// 更新一条
db.集合.updateOne(
   <query>,   // update的查询条件,一般写法:{"属性":{条件:值}}
   <update>,  // update的更新数据,一般写法 { $set:{"属性":"值",....} } 或者 { $inc:{"属性":"值"} }
   {
     upsert: <boolean>, // 可选参数,如果文档不存在,是否插入objNew, true为插入,默认是false,不插入
     multi: <boolean>,  // 可选参数,是否把满足条件的所有数据全部更新,设置更新1条还是多条
     writeConcern: <document> // 可选参数,抛出异常的级别。
   }
)

// 更新多条
db.集合.updateMany(
   <query>,   // update的查询条件,一般写法:{"属性":{条件:值}}
   <update>,  // update的对象,一般写法 { $set:{"属性":"值"} } 或者 { $inc:{"属性":"值"} }
   {
     upsert: <boolean>, // 可选参数,如果文档不存在,是否插入objNew, true为插入,默认是false,不插入
     multi: <boolean>,  // 可选参数,是否把满足条件的所有数据全部更新
     writeConcern: <document> // 可选参数,抛出异常的级别。
   }
)

image-20221015224318503

update更新运算符[修改器]

操作语法
$incdb.集合.update({<key1>:<val1>},{$inc:{<key2>:<val2>}})更新key1=val1的文档中key2的值为val2,类似python的递增递减 递减,则{ $inc:{<key2>:-<val2>} }
$setdb.集合.update({<key1>:<val>}, {$set:{<key2>:<val2>}})更新key1=val1的文档中key2的值为val2,如果key2不存在则新增对应键值对
$unsetdb.集合.update({<key1>:<val>}, {$unset:{<key2>:<val2>}})移除key1=val1的文档中key2=val2这个键值对
$pushdb.集合.update({<key1>:<val>}, {$push:{<key2>:<val2>}})给key1=val1的文档中key2列表增加1个数组成员val2。 key2必须是数组。
$pulldb.集合.update({<key1>:<val>}, {$pull:{<key2>:<val2>}})与push相反,给key1=val1的文档中key2列表删除1个指定成员val2
$popdb.集合.update({<key1>:<val>}, {$pop:{<key2>:<val2>}})给key1=val1的文档中key2列表移除第一个或最后一个成员。 val2只能是1(最后面)或-1(最前面),与python相反

终端操作:

// $inc
// 把laoli的年龄+10岁
db.user_list.update({"name":"laoli"},{$inc:{"age":10}}); // 更新一条
db.user_list.updateMany({"name":"xiaoming"},{$inc:{"age":10}}); // 更新多条
// 把laoli的孩子年龄+10岁
db.user_list.update({"name":"laoli"},{$inc:{"child.age":10}});


// $set
//更新laoli的手机号码
db.user_list.update({"name":"laoli"},{$set:{"mobile":"18012312312"}}); // 更新一条
// 更新laoli孩子的手机号码
db.user_list.update({"name":"laoli"},{$set:{"child.mobile":"18012312312"}});

// $unset
// 移除laoli的性别键值对
db.user_list.update({"name":"laoli"},{$unset:{"sex":true}});

// $push
db.user_list.update({"name":"laoli"},{$set:{"lve":["TV","game"]}});
db.user_list.update({"name":"laoli"},{$push:{"lve":"code"}}); // 往列表属性中追加成员

// $addToSet 结合 $each 把一个数组中每一个成员添加到数组中
db.user_list.update({"name":"laoli"},{$addToSet:{"lve":{$each:["code","music","TV"]}}});

// $pull
db.user_list.update({"name":"laoli"},{$pull:{"lve":"TV"}});

// $pop
db.user_list.update({"name":"laoli"},{$pop:{"lve":-1}}); // 左边移除列表的第一个成员
db.user_list.update({"name":"laoli"},{$pop:{"lve":1}}); // 右边移除列表的最后一个成员

// $rename 字段名重命名
db.user_list.update({"name":"laoli"},{$rename:{"lve":"love"}});

7.索引操作

在学习 MySQL 的时候,我们知道数据库里给数据构建索引通常能够极大的提高数据查询的效率,缩短查询耗时,如果没有索引,数据库在查询数据时必然会扫描数据表中的每个记录并提取那些符合查询条件的记录。

在 MongoDB 中构建索引也可以提高数据的查询效率和缩短查询耗时,没有索引的情况也是一样,MongoDB也会再查询数据时扫描集合中的每个文档并提取符合查询条件的文档。这种扫描全集合的查讯效率是非常地下的,特别是在处理大量数据的情况下,查询时间甚至可以达到几十秒钟甚至几分钟,这对用户体验来说是非常致命的。

准备数据

use demo
fotmatnumber = (start, end)=>{
    num = Math.round(Math.random() * (end-start)) + start
    if(num<10){
        return "0"+num;
    }else{
        return num;
    }
}

rand_title = (i)=>{
    num = Math.round( Math.random() * 10 );
    num1 = Math.round( Math.random() * 10 );
    return [
        "赠送礼品-"+num,
        "购物狂欢-"+num,
        "随便买买-"+num,
        "愉快购物-"+num,
        "赠送礼物-"+num,
        "商品购买-"+num,
        "买多送多-"+num,
        "买年货-"+num,
        "买买买买-"+num,
        "充值会员-"+num
    ][num1];
}

for(var i=0; i<200000; i++){  
    db.orders.insert({
        "onumber": ( "0000000000000000" + i ).substr( String(i).length ),  
        "date": "20"+fotmatnumber(0,21)+"-"+fotmatnumber(1,12)+"-"+fotmatnumber(1,31),  
        "title": rand_title(i),
        "user_id": parseInt(i/200)+1,
        "items" :[{ 
        	"goods_id" : parseInt(i/200)+1,
        	"goods_attr" : i,  
        	"price" : 100.0
        },{ 
        	"goods_id" : parseInt(i/200)+2,
        	"goods_attr" : i+1,  
        	"price" : 80.0
        }]
    })
    if(i%10000==0){
        print("已经添加了"+parseInt(i/10000)+"万条数据!");
    }
}

上述 for 循环的执行是因为 mongo 内嵌了 js 的解释引擎;

  1. MongoDB的索引存储运行内存(RAM)中的,所以必须确保索引的大小不超过内存的限制。如果索引的大小超过了运行内存的限制,MongoDB会删除一些索引,这将导致性能下降。
  2. MongoDB的索引在部分查询条件下是不会生效的。
    • 正则表达式及非操作符,如 $nin,$not , 等。
    • 算术运算符,如 $mod, 等。
    • $where自定义查询函数。
  3. 索引会在写入数据(添加、更新和删除)时重排,如果项目如果是写多读少,则建议少使用或者不要使用索引。
  4. 一个集合中索引数量不能超过64个。
  5. 索引名的长度不能超过128个字符。
  6. 一个复合索引最多可以有31个字段。
  7. mongodb索引统一在system.indexes集合中管理。这个集合只能通过createIndexdropIndexes来操作

7.1 查看索引

// 获取当前集合中已经创建的所有索引信息
db.集合.getIndexes()
/*
[{ 
	"v" : 2,   // 索引版本
	"key" : {  // 索引的字段及排序方向(1表示升序,-1表示降序)
		"_id" : 1   // 根据_id字段升序索引
    }, 
    "name" : "_id"   // 索引的名称
}]
*/
// 获取当前集合中已经创建的索引总大小,以字节为单位返回结果
db.集合.totalIndexSize()
// 获取当前数据库中所有的索引【不会显示_id主键】
db.system.indexes.find()

MongoDB 默认为插入文档生成_id字段(如果本身没有指定改字段),_id是文档的唯一标识,为了保证能根据文档 id 快速查询文档,MongoDB 默认会为集合创建_id字段的主键索引。

7.2 查询分析

与 SQL 语句类似,MongoDB 也提供了一个 explain,供开发者进行查询分析.

explain 的使用有 3 个参数,分别是 queryPlanner、executionStats、allPlansExecution,默认是queryPlanner,开发中常用的是executionStats。

db.orders.find({"title":"购买商品-19"}).explain("executionStats");
/*
{
	"queryPlanner" : {  # 被查询优化器选择出来的查询计划
		"plannerVersion" : 1,  # 查询计划版本
		"namespace" : "test.orders", # 要查询的集合
		"indexFilterSet" : false,  # 是否了使用索引
		"parsedQuery" : {  # 查询条件
			"title" : {
				"$eq" : "购买商品-19"
			}
		},
		"winningPlan" : {     # 最佳执行计划
			"stage" : "COLLSCAN", # 扫描类型/扫描阶段
			"filter" : {     # 过滤条件
				"title" : {
					"$eq" : "购买商品-19"
				}
			},
			"direction" : "forward"  # 查询方向,forward为升序,backward表示倒序。
		},
		"rejectedPlans" : [ ]   # 拒绝的执行计划
	},
	"executionStats" : {  # 最佳执行计划的一些统计信息
		"executionSuccess" : true,  # 是否执行成功
		"nReturned" : 1,   # 返回的结果数
		"executionTimeMillis" : 346,  # 执行耗时
		"totalKeysExamined" : 0,      # 索引扫描次数
		"totalDocsExamined" : 1000000,  # 文档扫描次数,所谓的优化无非是让totalDocsExamined和nReturned的值接近。
		"executionStages" : {     # 执行状态
			"stage" : "COLLSCAN",  # 扫描方式/扫描阶段
			"filter" : {
				"title" : {
					"$eq" : "购买商品-19"
				}
			},
			"nReturned" : 1,   # 返回的结果数
			"executionTimeMillisEstimate" : 5,   # 预估耗时
			"works" : 1000002,   # 工作单元数
			"advanced" : 1,      # 优先返回的结果数
			"needTime" : 1000000,
			"needYield" : 0,
			"saveState" : 1000,
			"restoreState" : 1000,
			"isEOF" : 1,
			"direction" : "forward",
			"docsExamined" : 1000000   # 文档检查数目,与totalDocsExamined一致
		}
	},
	"serverInfo" : {   # 服务器信息
		"host" : "ubuntu",
		"port" : 27017,
		"version" : "4.4.2",
		"gitVersion" : "15e73dc5738d2278b688f8929aee605fe4279b0e"
	},
	"ok" : 1
}

*/

stage的扫描类型:

类型名称描述期望
COLLSCAN全表扫描False
IXSCAN索引扫描True
FETCH根据索引去检索指定documentTrue
IDHACK针对_id进行查询True
COUNTSCANcount不使用Index进行count时返回False
COUNT_SCANcount使用了Index进行count时返回True
SUBPLA未使用到索引的$or查询时返回False
TEXT使用全文索引进行查询时返回-
SORT使用sort排序但是无index时返回False
SKIP使用skip跳过但是无index时返回False
PROJECTION使用limit限定结果但是无index时返回False

7.3 创建索引

MongoDB支持多种类型的索引,包括普通索引、复合索引、多列索引、全文索引、哈希索引地理位置索引等,每种类型的索引有不同的使用场合。ttl索引本质上就是普通索引。另外,MongoDB的全文索引很弱智,如果真要用在开发中,还是建议使用elasticsearch或者Sphinx。

// 创建索引
db.集合.createIndex({
    // 单个字段,则为普通索引,    // sort的值表示排序,值为1表示升序索引,-1表示降序索引
    "字段名1": <sort|type>,       // type的值可以是text,表示创建全文索引。db.集合.find({$text:{$search:"字符串"}})
    "字段名2": <sort|type>,       // 多个字段,则为复合索引
    "字段名3": [<1>,<2>,...],  // 多列索引
    ....
}, {
    background: <Boolean>,   // 建索引过程会阻塞其它数据库操作,background可指定以后台方式创建索引,默认为false
    unique: <Boolean>,  // 是否建立唯一索引,默认值为false,也叫唯一索引
    name: <String>,   // 索引的名称,不填写,则MongoDB会通过连接索引的字段名和排序顺序生成一个索引名称 
    expireAfterSeconds: <integer>, // 设置索引的过期时间,类似redis的expire,也叫TTL索引
    sparse: <Boolean>,  // 对文档中不存在的字段数据是否不启用索引,默认为False
});


// 单字段索引[普通索引]
 db.集合.createIndex({
    "字段名1": <sort>,    // sort的值表示排序,值为1表示升序索引,-1表示降序索引
 }, {
	....
 })
// 普通索引创建: db.orders.createIndex({"title":1})
// 查询基本使用: db.orders.find({"title":"愉快购物-7"}).explain("executionStats");


// 多字段索引,也叫复合索引。[类似mysql里面的联合索引]
 db.集合.createIndex({
    "字段名1": <sort>,    // sort的值表示排序,值为1表示升序索引,-1表示降序索引
    "字段名2": <sort>,    // sort的值表示排序,值为1表示升序索引,-1表示降序索引
 }, {
	....
 })

// 复合索引的使用对单字段条件的查找是没有帮助的,必须多字段[必须包含复合索引的字段]条件使用
// 复合索引创建:db.orders.createIndex({"date":1,"title":1});
// 查询基本使用:
//     db.orders.find({"date":"2020-09-01","title":"购买商品-1007"}).explain("executionStats");
//     db.orders.find({"date":"2020-09-01","onumber":"0000000000001007","title":"购买商品-1007","onumber":});


// 全文索引
 db.集合.createIndex({
    "字段名1": <type>,    // type的值只能是text,表示创建全文索引。db.集合.find({$text:{$search:"字符串"}})
 }, {
	....
 })

// 全文索引创建: db.orders.createIndex({"title":"text"})
// 查询基本使用: db.orders.find({$text:{$search:"商品-19"}}).explain("executionStats")



// 多列索引[应用的地方是在列表属性]
 db.集合.createIndex({
    "字段名3": [<1>,<2>,...],
 }, {
	....
 });

// 创建测试数据
db.doc.drop()
db.doc.insert({"title":"标题1","tags":["python","django"]})
db.doc.insert({"title":"标题1","tags":["python","django"]})
db.doc.insert({"title":"标题1","tags":["python","django"]})
db.doc.insert({"title":"标题2","tags":["java","mvp"]})
db.doc.insert({"title":"标题3","tags":["java","mvp"]})
db.doc.insert({"title":"标题2","tags":["java","mvp"]})
db.doc.insert({"title":"标题3","tags":["python"]})
db.doc.insert({"title":"标题4","tags":["python"]})
db.doc.insert({"title":"标题2","tags":["python","flask"]})
db.doc.insert({"title":"标题3","tags":["java"]})
// 创建多列索引: db.doc.createIndex({"tags":1})
// 查询数据: db.doc.find({"tags":["python"]}).explain("executionStats")



// 唯一索引
db.集合.createIndex({
    "字段名1": <sort>,
}, {
    unique: true,     // 是否建立唯一索引,默认值为false,也叫唯一索引
})
// 创建唯一索引: db.orders.createIndex({"onumber":1},{unique:true});
// 查询数据: db.orders.find({"onumber":"0000000000001019"}).explain("executionStats")



// ttl索引
// 使用ttl索引,索引关键字段必须是 Date 类型,如果该字段不是date类型或者文档中不存在该字段,则文档不会进行过期处理
// 数据过期的删除工作是在独立线程内执行的,默认平均60s扫描一次。

// 例如:在文档创建10秒后删除文档【有问题,不能及时删除】
db.orders.dropIndex("date_1")
db.orders.createIndex({"date": 1},{expireAfterSeconds: 10})
db.orders.insertOne({
   "date": "2021-10-02", // 在python中需要通过 utctime
   "user_id": 2,
   "username": "xiaohong"
})

// 在文档创建后,由索引字段值指定的时间删除文档
db.orders.createIndex({"date": 1},{expireAfterSeconds: 0}) // 文档中date字段对应的时间就变成了过期时间了.
db.orders.insert( {
   "date": new Date('2021-10-02 11:40:00'), // 在python中需要通过 utctime
   "user_id": 2,
   "username": "xiaoming"
})

// 创建索引:db.tasks.createIndex({"expire_time":1},{expireAfterSeconds:0})
// 创建测试数据
db.tasks.insert( {
   "expire_time": new Date('2021-10-02 11:43:00'), // 在python中需要通过 utctime
   "user_id": 2,
   "username": "xiaoming"
});

db.tasks.insert( {
   "expire_time": new Date('2021-10-02 11:43:00'), // 在python中需要通过 utctime
   "user_id": 2,
   "username": "xiaoming"
});
db.tasks.insert( {
   "expire_time": new Date('2021-10-02 11:43:00'), // 在python中需要通过 utctime
   "user_id": 2,
   "username": "xiaoming"
});

// 重建索引[一般是在长期项目运行下来,索引创建时间太久了,性能下降的时候使用。不能在高峰期时运行]
db.集合.reIndex();

7.4 删除索引

MongoDB给文档主键_id默认创建单字段索引是无法删除的。

// 删除单个索引
db.集合.dropIndex("索引名称")

// 删除所有索引,慎用
db.集合.dropIndexes()
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值