目录
一、理论
1.MongoDB文档管理
2.MongoDB索引管理
二、实验
1.MongoDB文档管理
2.MongoDB索引管理(索引添加与删除)
3.MongoDB索引管理(全文索引)
4.MongoDB索引管理(多列索引)
5.MongoDB索引管理(ttl索引)
三、问题
1.查询执行情况报错
2.创建索引失败
3.find查询报错
(1)数据类型
表1 数据类型
Type | 描述 |
---|---|
ObjectID | 用于存储文档的ID,相当于主键,区分文档的唯一字段,mongoDB中就是一个对象的返回值 |
String | 字符串是最常用的数据类型,MongoDB中的字符串必须是UTF-8编码。 |
Integer | 整数类型用于存储数值。整数可以是32位,也可以是64位,这取决于你的服务器。 |
Double | 双精度类型用于存储浮点值,mongodb中没有float浮点数这个说法 |
Boolean | 布尔类型用于存储布尔值(true/ false) |
Arrays | 将数组、列表或多个值存储到一个键,[] |
Timestamp | 时间戳,用于记录文档何时被修改或创建。Date(),Timestamp(),ISODate() |
Object | 用于嵌入文档, 相当于子属性是另一个json文档而已,这种方式就可以实现嵌套。 [] |
Null | 空值,相当于 python的None |
Symbol | 与字符串用法相同,常用于某些使用特殊符号的语言,二进制 |
Date | 用于以UNIX时间格式存储当前日期或时间。 |
Binary data | 二进制数据,常用于保存文件的内容,往往是图片,数据本身。 |
Code | 用于将JavaScript代码存储到文档中 |
Regular expression | 正则表达式 |
(2)条件运算符(查询器)
①比较运算
表2 比较运算
操作 | 格式 | 语法例子 | SQL中的类似语句 |
等于 | { } { |
db.集合.find({"name":"xiaoming"}) |
where name = 'xiaoming' |
小于 | { |
db.集合.find({"age":{$lt:17}}) | where age < 17 |
小于或等于 | { |
db.集合.find({"age":{$lte:17}}) | where age <= 17 |
大于 | { |
db.集合.find({"age":{$gt:17}}) | where age > 17 |
大于或等于 | { |
db.集合.find({"age":{$gte:17}}) | where age >= 17 |
不等于 | { |
db.集合.find({"age":{$ne:17}}) | where age != 17 |
包含 | { |
db.集合.find({"age":{$in:[1,2,3]}}) | where age in (1,2,3) |
②逻辑运算
表3 逻辑运算
操作 | 语法 | 语法例子 |
$and |
{ {$and: [{key:{$运算符: |
db.集合.find({key1:value1, key2:value2}) |
$or | {$or: [{ |
db.集合.find({$or: [{key1: value1}, {key2:value2}]}) |
$and 和$or |
`{ `{$and:[{$or:[{ |
db.集合.find({key1:value1, $or: [{key1: value1}, {key2:value2}]}) |
$not | { |
`$not`操作符不支持``$regex`正则表达式操作 |
③其他运算符
表4 其他运算符
操作 | 格式 | 法例子 | 说明 |
$type | { |
db.集合.find({"name":{$type:'string'}}) | 匹配指定键是指定数据类型的文档 number 数值型 string 字符串 bool 布尔类型 object json文档对象类型 array 数组类型 |
$exists |
{ |
db.集合.find({"title":{$exists:true}}) |
匹配具有指定键的文档,存在指定字段的文档 |
$regex | `{ `{ |
db.集合.find({"name":{$regex:/张$/}}) | 按正则匹配 |
$mod | { |
db.集合.find({"age":{$mod:[10,0]}}) | 算数运算,取模,语法中举例是age除以10==0 |
(3) update更新运算符(修改器)
表5 update更新运算符
操作 | 语法 | 说明 |
$inc |
db.集合.update({ |
更新key1=val1的文档中key2的值为val2,类似python的递增递减 递减,则`{ $inc:{ |
$set |
db.集合.update({ |
更新key1=val1的文档中key2的值为val2,如果key2不存在则新增对应键值对 |
$unset |
db.集合.update({ |
移除key1=val1的文档中key2=val2这个键值对 |
$push |
db.集合.update({ |
给key1=val1的文档中key2列表增加1个数组成员val2。 key2必须是数组。 |
$pull | db.集合.update({ |
与push相反,给key1=val1的文档中key2列表删除1个指定成员val2 |
$pop |
db.集合.update({ |
给key1=val1的文档中key2列表移除第一个或最后一个成员。 val2只能是1(最后面)或-1(最前面),与python相反 |
(1)stage的扫描类型
表6 stage的扫描类型
类型名称 | 描述 | 期望 |
COLLSCAN | 全表扫描 | False |
IXSCAN | 索引扫描 | True |
FETCH | 根据索引去检索指定document | True |
IDHACK | 针对_id进行查询 | True |
COUNTSCAN | count不使用Index进行count时返回 | False |
COUNT_SCAN | count使用了Index进行count时返回 | True |
SUBPLA | 未使用到索引的$or查询时返回 | False |
TEXT | 使用全文索引进行查询时返回 | - |
SORT | 使用sort排序但是无index时返回 | False |
SKIP | 使用skip跳过但是无index时返回 | False |
PROJECTION | 使用limit限定结果但是无index时返回 | False |
(2)注意事项
1) MongoDB的索引是存储在运行内存(RAM)中的,所以必须确保索引的大小不超过内存的限制。
如果索引的大小超过了运行内存的限制,MongoDB会删除一些索引,这将导致性能下降。
2) MongoDB的索引在部分查询条件下是不会生效的。
- 正则表达式及非操作符,如 `$nin`,`$not` , 等。
- 算术运算符,如 $mod, 等。
- $where自定义查询函数。
- ...
3)索引会在写入数据(添加、更新和删除)时重排,如果项目如果是写多读少,则建议少使用或者不要使用索引。
4) 一个集合中索引数量不能超过64个。
5) 索引名的长度不能超过128个字符。
6) 一个复合索引最多可以有31个字段。
7) mongodb索引统一在`system.indexes`集合中管理。这个集合只能通过`createIndex`和`dropIndexes`来操作。
(1)排序
(2)regex 正则匹配
(3)取年龄
(4)前5个和第6个开始
db.user_list.find({},{"_id":0,"name":1,"age":1}).sort({"age":1}).limit(5);
(6)laoli 减去2岁
db.user_list.updateMany({name:"laoli"},{$inc:{age:-2}})
(7)xiaoming都改为20岁
db.user_list.updateMany({name:"xiaoming"},{$set:{age:20}})
(8)xiaoming都增加2岁
> db.user_list.updateMany({name:"xiaoming"},{$inc:{age:2}})
(9)删除所有有手机号的
db.user_list.updateMany({name:"xiaoming",mobile:{exists:true}},{$unset:{mobile:true}})
(10)往列表属性中追加成员
db.user_list.update({"name":"laoli"},{$push:{"lve":"code"}});
(11)删除列表成员
db.user_list.update({"name":"laoli"},{$pull:{"lve":"TV"}});
(12)$addToSet 结合 $each 把一个数组中每一个成员添加到数组中
db.user_list.update({"name":"laoli"},{$addToSet:{"lve":{$each:["run","swim","ball"]}}});
(13)左边移除列表的第一个成员
db.user_list.update({"name":"laoli"},{$pop:{"lve":-1}});
(14)右边移除列表的最后一个成员
db.user_list.update({"name":"laoli"},{$pop:{"lve":1}});
(15)$rename 字段名重命名
db.user_list.update({"name":"laoli"},{$rename:{"lve":"love"}});
(1)获取当前集合中已经创建的索引总大小,以字节为单位返回结果
(2)获取当前数据库中所有的索引(不会显示_id主键)
(3)查询MongoDB
(4)查询1条数据,准备用user_id做 索引
> db.orders.find({user_id:10}).count()
200
> db.orders.find({user_id:101}).count()
200
> db.orders.find({user_id:101}).explain("executionStats");
(7)倒叙查询,显示先查询(104M数据)再索引
(8)索引迭代2个版本
(9)3微秒执行402次
(10)执行完成
(11)准备选取2个做索引
(12)创建索引
(13)查看索引数量(第一个为默认的主键索引,第二个为单字段普通索引,第三个为多字段索引)
(14)走了索引
db.orders.find({"date":"2020-09-01"}).explain("executionStats");
(15)还是走了索引(只要有1个满足就会走索引)
db.orders.find({"date":"2020-09-01","onumber":"0000000000001007"}).explain("executionStats");
(16)没条件满足会走全表扫描
db.orders.find({"title":"购买商品-1007","onumber":"0000000000001007"}).explain("executionStats");
(17)删除单字段索引
(18)删除多字段索引
> db.orders.dropIndex("user_id_1")
{ "nIndexesWas" : 3, "ok" : 1 }
> db.orders.getIndexes()
(19)全表扫描
> db.orders.find({"date":"2020-04-17","title":"赠送礼品-10"});
> db.orders.find({"date":"2020-09-01","title":"赠送礼品-10"}).explain("executionStats");
(20)添加多字段索引,查询为索引扫描
> db.orders.createIndex({"date":1,"user_id":1});
> db.orders.find({"date":"2020-09-01","title":"赠送礼品-10"}).explain("executionStats");
(1)默认支持英文
(2)查询基本使用,命中全文索引
db.orders.find({$text:{$search:"商品-19"}}).explain("executionStats")
(3)还有倒序步骤
(1)创建测试数据
(2)添加唯一索引
db.orders.createIndex({"onumber":1},{unique:true});
(3)查看索引
db.orders.getIndexes()
(4)获取索引大小(包含全文和唯一索引)
db.orders.totalIndexSize()
(5)索引扫描
db.orders.find({"onumber":"0000000000001019"}).explain("executionStats")
(6)创建doc表并查询索引
(7)删除后变成全表扫描
(7)删除orders表全文索引查看大小
(8)已命中
(9)删除索引
> db.orders.dropIndexes("onumber_1")
> db.orders.getIndexes()
(1)在文档创建10秒后删除文档
(2)插入显示已被删除
(3)删除索引
(4)新建索引
(5)都已删除
(1)问题
(2)语法错误
语法错误修改命令
(3)解决方法
修改命令
(1)问题
(2)原因分析
语法错误
(3)解决方法
修改命令
(1)报错
(2)原因分析
语法错误
(3)解决方法
修改命令