# 管理单元
MongoDB 的管理单元从上到下依次分为:
- database
- :数据库,相当于 MySQL 的数据库。
- 一个 MongoDB 服务器中可以存储多个 database 。
- collection
- :集合,相当于 MySQL 的数据表。
- 每个 database 中可以存储多个 collection 。
- document
- :文档,相当于 MySQL 的数据行。
- 每个 collection 中可以存储多个 document 。
# database
MongoDB 中默认有三个数据库。
- admin :保存用户的信息。
- local :该数据库不会被复制,常用于保存一些仅限本机使用的集合。
- config :保存配置信息。
# 查
show dbs // 显示所有数据库的名字、占用磁盘
use db1 // 切换到指定数据库
db // 显示当前数据库的名字
db.stats() // 显示当前数据库的状态信息
db.getMongo() // 显示当前数据库存储在哪个主机上
db.getSiblingDB('db1').stats() // 根据名称获得一个数据库对象的引用
- MongoDB 没有提供数据库的 create 命令。但可以用 use 命令切换到一个不存在的数据库,进行写操作时会自动创建它。
- 通过
db.runCommand(...)
可执行一些非 CRUD 类型的数据库命令,此时会与一个内置的虚拟集合$cmd
交互。
# 删
db.dropDatabase() // 删除当前数据库
# collection
# 查
show collections // 显示当前数据库的所有集合,也可执行 show tables
db.c1 // 通过数据库成员的方式获得指定集合的引用,此时集合名必须遵循 C 语言命名风格
db.getCollection('c1') // 根据名称获得一个集合的引用
db.<collection>.stats() // 显示指定集合的状态信息
db.<collection>.stats().count // 集合中的文档数,不包括已标记为 deleted 的文档
- 例:遍历所有数据库的所有集合
db.adminCommand("listDatabases").databases.forEach(function(d){ db = db.getSiblingDB(d.name); cols = db.getCollectionNames(); cols.forEach(function(col){ print(col, db.getCollection(col).stats().size); }); });
# 增
db.createCollection('c1') // 创建集合
db.createCollection('c1', {max:1000})
db.createCollection('c1', {capped:true, size:10000})
- max :可选参数,表示集合中最多可以包含的文档数量,单位为个。
- 当集合满了时(达到 max 或 size),新插入的文档会从集合头部开始存储,覆盖旧文档。
- capped、size :一对搭配使用的可选参数,表示创建固定大小的集合,单位为 KB 。
- 固定集合的插入、查询速度很快,还会记住每个文档的插入顺序,但是不能删除其中的文档,只能删除整个集合。
# 改
db.getCollection('c1').renameCollection('c2'); // 重命名集合
# 删
db.<collection>.drop() // 删除集合
# document
文档采用 BSON 格式存储数据,特点如下:
- 与 JSON 的语法类似。
- 以二进制形式存储数据。
- BSON 中的键值对是有序存储的,区分大小写。
- key 只能是 String 类型,取值不能重复。
- 以下划线 _ 开头的 key 是保留的,用户不应该使用。
- value 可以是以下类型:
- 与 JSON 相似的数据类型:
- null
- Number
- Boolean
- String(采用 utf-8 编码)
- Array
- Object(嵌套另一个文档)
- ObjectId :文档 ID
- 占 12 bytes ,是每个文档的唯一标识符。
- 例如 62a03eb3ec744e00015b1f26 ,用 4 bytes 存储创建该文档的时间戳,用 3 bytes 存储该主机的 ID ,用 2 bytes 存储进程的 PID ,最后 3 bytes 是随机数。
- Timestamp :时间戳
- 占 8 bytes 。前 4 bytes 是 UTC 时间戳(精确到秒),后 4 bytes 是在该秒中的操作序号。
- 主要被 MongoDB 内部使用。
- Date :日期
- 精确到毫秒,可以用 Date() 函数获取。
- 与 JSON 相似的数据类型:
# 查
db.<collection>.find([query], [projection]) // 返回所有匹配的文档
db.<collection>.findOne([query], [projection]) // 返回第一个匹配的文档
query 参数表示查询条件,相当于 MySQL 的 where 子句。
- 如果 query 参数为空或 { } ,则匹配所有文档。
- 例:
{"_id": ObjectId("62a03eb3ec744e00015b1f26")} // 查询字段 _id 等于指定值的文档 {"_id": {"$eq": {"$oid": "62a03eb3ec744e00015b1f26"}}} // ObjectId() 函数只能在 Mongo Shell 中执行,在 JSON 中需要使用 $oid 的格式,比如显示慢日志时会自动转换成 $oid {"name": "leo"} {"student.id": 1} // 可以选择子字段 {"students.1.id": 1} // 这里 students 是 array 类型,选取其中第 1 个元素的 id 字段 {"name": {"$type":"string"}} // 字段 name 为 string 类型 {"age": {"$gt":0, "$lt":10}} // 字段 age 大于 0、小于 10 {"age": {"$gte":0, "$lte":10}} // 字段 age 大于等于 0、小于等于 10 {"age": {"$in":(10,11,12)} // 字段 age 使用指定的某个值 {"tags": {"$all":[1,2,3]}} // 字段 tags 是 array 类型,且包含指定的所有值
- 查询某个 ObjectId 所属的时刻:
ObjectId("62a03eb3ec744e00015b1f26").getTimestamp()
- 查询在指定时刻之后创建的文档:
id1 = Math.floor((new ISODate('2022-01-01T00:00:00+08:00'))/1000).toString(16) + '0000000000000000'; db.getCollection('test').find({_id:{$gte: ObjectId(id1)}}).count();
projection 参数用于筛选 query 的查询结果,用 1、0 表示是否返回某个字段。筛选多个字段时,只能同时为 1 或 0 。
- 例:
db.c1.find({"name":"leo"}, {"_id": 1, "name": 1})
- 例:
查询结果的可用方法:
db.<collection>.find().pretty() // 显示时进行换行、缩进 .limit(10) // 最多返回 10 个匹配的文档 .count() // 不返回文档,而是计数 .sort({"_id":1}) // 按某个字段进行排序(1 表示升序,-1 表示降序) db.<collection>.find().pretty().limit(10) // 可嵌套使用多个方法
- 使用 limit(n) 时,只要查询到 n 条文档就停止查询,不必遍历所有文档,因此查询耗时、占用内存少。
- 如果直接执行
db.<collection>.count()
,则会估算集合的文档数,不会遍历所有文档,因此不一定准确。
# 增
db.<collection>.insertOne({...}) // 往集合中插入一个文档
db.<collection>.insertMany([{...}, {...}]) // 以数组的形式插入多个文档
- 新增文档时,如果指定的集合不存在,则会自动创建它。
- 默认将 _id 字段设置成主键,并建立索引。
- 如果没有输入 _id 字段,则会自动添加。如果输入了 _id 字段,则会覆盖原来的值。
- 每个集合可写入的文档数量没有上限,但单个 BSON 文档的体积最大为 16MB 。
# 改
db.<collection>.updateOne([query], <update>) // 修改第一个匹配的文档
db.<collection>.updateMany([query], <update>) // 修改所有匹配的文档
- update 参数表示要执行的操作。
- 例:
db.c1.updateOne({"name":"leo"}, {$set:{"name":"Leo"}})
- 常用的操作类型:
$set // 设置字段 $unset // 删除字段 $rename // 修改字段的名称。例如:$rename:{"a":"b"} $inc // 对数字类型的字段进行加减 $push // 向 array 类型的字段中添加一个值。例如:$push:{"tags":"a"} $pushAll // 向 array 类型的字段中添加多个值。例如:$push:{"tags":[1,2,3]} $pull // 从 array 类型的字段中删除一个值。例如:$pull:{"tags":"a"} $pullAll // 从 array 类型的字段中删除多个值。例如:$pull:{"tags":[1,2,3]} $pop // 用 1、-1 分别表示删除最后一个值、第一个值。例如:$pop:{"tags":1}
- 例:
# 删
db.<collection>.deleteOne([query]) // 删除第一个匹配的文档
db.<collection>.deleteMany([query]) // 删除所有匹配的文档
# index
- 一个 collection 可以针对多个字段创建多个 index ,用于加速查询。
- 每个集合默认有一个针对 _id 字段的索引,用户还可创建其它索引。
- 支持创建由多个字段组成的复合索引。
# 查
db.<collection>.getIndexes() // 显示所有索引
db.<collection>.totalIndexSize() // 显示全部索引的大小
# 增
db.<collection>.createIndex(<keys>, [options])
- 例:
db.c1.createIndex({"title":1}, {"name": "index_1"}) // 对一个字段创建索引(1 表示升序,-1 表示降序) db.c1.createIndex({"title":1, "tags":-1}) // 对多个字段创建索引
- 常用的 options 参数:
- name :该索引的名称。未指定的话会自动命名。
- unique :是否限制该字段的取值唯一。默认为 false 。
- background :是否在后台创建索引。默认为 false ,会阻塞前台进程。
- expireAfterSeconds :设置过期时间,过期之后一段时间内会自动删除该文档。(只能作用于 Date 类型的字段)
- v :索引的版本号。
# 删
db.<collection>.dropIndex("name_1") // 删除指定索引
db.<collection>.dropIndexes() // 删除所有索引
db.<collection>.reIndex() // 重新建立索引,该操作的开销较大