本节笔记记录 Mongodb 的常用命令, 包括创建数据库(文档)、删除数据库(文档) 以及增删改查.
首先, 要先进入 Mongodb Client 交互环境:
> mongo MongoDB shell version: 3.0.6 connecting to: test ...
创建数据库(文档)
命令格式:
use DATABASE_NAME
如果数据库不存在, 则创建数据库并切换过去, 否则直接切换到指定数据库.
实例:
> use runoob switched to db runoob > db runoob >
现在我们创建一个新数据库 runoob, 然后 db 命令查看当前所在的数据库, 就会当前环境看到已经切换到 runoob 数据库中了..
使用 show dbs 命令可以查看所有已存在的数据库:
> show dbs local 0.078GB test 0.078GB >
但是, 我们发现刚创建的数据库 runoob 并不在数据库的列表中, 要显示它, 我们需要向 runoob 数据库插入一些数据, 关于如何插入数据, 请参考下面的笔记.
删除数据库(文档)
命令格式:
db.dropDatabase()
删除当前所在数据库
实例:
首先, 查看所有数据库:
> show dbs local 0.078GB runoob 0.078GB test 0.078GB
切换到待删除数据库 runoob:
> use runoob switched to db runoob >
执行删除命令:
> db.dropDatabase() {"dropped": "runoob", "ok": 1}
最后, 再通过 show dbs 命令数据库是否删除成功:
> show dbs local 0.078GB test 0.078GB >
插入数据
命令格式:
MongoDB 使用 insert() 或 save() 方法向集合中插入文档:
db.COLLECTION_NAME.insert(document)
这里提到一个集合 和 document 的概念.
什么是集合?
用常规的思维来说, 集合对应的就是数据库中的表, 当我们插入数据的时候, 是向”表”中插入数据.
现在可以总结出 Mongodb 与 MySQL 对照关系如下:
Mongodb | MySQL |
---|---|
文档 | 数据库 |
集合 | 表 |
OK, 现在知道什么是集合了, 那什么是 document?
- 文档的数据结构和 JSON 基本一样
- 所有存储在集合中的数据都是 BSON 格式
- BSON 是类 json 的一种二进制形式的存储格式, 即 Binary JSON
对于常用 Python 的我来说, 更喜欢把它说成是一种 Dict 结构.
实例:
首先, 创建一个新数据库:
> use runoob switched to db runoob > db runoob >
然后向 runoob 数据库的 col 集合中插入数据:
>db.col.insert({name: 'MongoDB 教程', age: 18})
col 是我们的集合名, 如果该集合不在当前所处的数据库中, MongoDB 会自动创建该集合并插入文档.
MongoDB 数据中的字段都是字符串格式的, 但是 MongoDB 做了优化, 通常我们可以可以省略引号.
每个已插入的数据, MongoDB 都会为它分配一个 _id 字段, 当然, 也可以在插入数据时显示的指定 _id 字段, 但是要注意, _id 字段是不可重复的, 如果使用 insert() 插入相同 _id 的数据, 会报错, 不过可以使用 save() 方法:
- 如果不指定 _id 字段 save() 方法类似于 insert() 方法
- 如果指定 _id 字段, 则会更新该 _id 的数据
- 如果指定 _id 不存在, 也类似于 insert() 方法
现在可以通过 find() 命令查看已插入的数据, 关于查询的命令详细用法请继续参考下面的笔记, 这里仅测试下 _id 字段…
> db.col.find() {"_id": ObjectId("56064886ade2f21f36b03134"), "name": "MongoDB 教程", "age": 18} >
可以看到刚才插入的数据有了一个 _id 字段, 使用该字段可以对数据进行 删、改、查.
删除文档
remove() 方法用来移除集合中的数据
命令格式:
db.collection.remove( {query}, {justOne} )
参数说明:
- query: 匹配条件条件, 如 {name: ‘张三’}
- justOne: 可选, 如果设为 true 或 1, 则只删除一个文档, 默认删除所有匹配文档, 如 {justOne: true}
如果想删除所有数据, 可以使用以下方式:
db.col.remove({})
修改数据
可以使用 update() 和 save() 方法来更新集合中的文档.
- update() 用于更新已存在的文档, 当然它也支持插入新文档, 但它的本质还是更新
- save() 通过传入的文档来替换已有文档, 它的本质是用新文档覆盖掉旧文档
update()
db.collection.update( {query}, {update}, { upsert: <boolean>, multi: <boolean>, writeConcern: <document> } )
参数说明:
- query: 匹配条件, 直接写 {} 表示匹配所有
- update: 更新内容, 支持多种操作符
- $set: {$set: {field: value}} 为 field 设置新值, 如果 field 不存在, 则为文档添加 field
- $unset: {$unset: {field: value}} 删除 field, 这里 value 为 true 或 1
- $inc: {$inc: {field: value}} field 的值加上 value, 支持负数
- $max: {$max: {field: value}} 增量修改, 只有 value 大于原有的 value 时, 才会修改成功
- $min: {$min: {field: value}} 减量修改, 只有 value 小于原有的 value 时, 才会修改成功
- $rename: {$rename: {old_field_name: new_field_name}} 字段重命名
- $setOnInsert: {$setOnInsert: {field: value}} 只有当是新插入时才执行, 所以要配合 upsert 使用
- upsert: 可选, {upsert: bool} 如果匹配失败, 是否插入新数据, 默认是 false, 不插入
- multi: 可选, {multi: bool} 是否更新多条数据, 默认是 false, 只更新找到的第一条记录, 如果这个参数为 true, 就把按条件查出来多条记录全部更新
- writeConcern: 可选, 抛出异常的级别
save()
db.collection.save( {document}, { writeConcern: <document> } )
参数说明:
- document: 文档数据
- writeConcern: 可选, 抛出异常的级别
查询数据
基础查询
命令格式:
MongoDB 使用 find() 或 findOne() 方法从集合中插查询数据:
>db.COLLECTION_NAME.find() >db.col.find().pretty()
find() 方法以非结构化的方式来显示所有文档, 如果需要以易读的结构化方式来读取数据, 可以使用 pretty() 方法.
实例
查询 col 集合中的数据:
> db.col.find().pretty() { "_id" : ObjectId("56063f17ade2f21f36b03133"), "name": "MongoDB 教程", "age": 18 }
细心同学可能已经发现, 上面查询结果中字段都是字符串格式(_id、name、age 都用引号包起来了).
过滤返回字段
通过 find() 的第二个参数可以指定返回的字段.
例如, 只想返回 name 字段:
> db.col.find({}, {'name': 1}).pretty() { "_id" : ObjectId("56063f17ade2f21f36b03133"), "name": "MongoDB 教程", }
注意, _id 总是返回的.
或者指定哪些字段不返回:
> db.col.find({}, {'_id': 0}).pretty() { "name": "MongoDB 教程", "age": 18 }
可以看到, 这种方式可以过滤掉 _id 字段.
条件查询
MongoDB 的 find() 和 findOne() 都支持条件语句的查询, 它们与 SQL 语句的对应关系如下表:
注意, MongoDB 的条件也是 document 类型(Dict)
操作 | 格式 | 范例 | SQL |
---|---|---|---|
等于 | db.col.find( | where name = ‘菜鸟教程’ | |
小于 | db.col.find( | where age < 50 | |
小于等于 | db.col.find( | where age <= 50 | |
大于 | db.col.find( | where age > 50 | |
大于等于 | db.col.find( | where age >= 50 | |
不等于 | db.col.find( | where age != 50 |
嵌套条件查询
因为 MongoDB 中存储的数据是 document(Dict), 所以有些 key 中保存的 value 可能是另一个 document(Dict), 此时, 我们可以用嵌套条件来查询到嵌套在 value 中的子 document(Dict), 语法格式就是点号.
先插入一条嵌套数据:
>db.col.insert({name: '张三', age: 18, school: {name: '交通大学', city: '上海'}})
如果想要根据学校名字来查询数据, 就可以用下面这种嵌套条件:
db.col.find({'school.name': '交通大学'}).pretty()
不包含字段查询
这种查询是查询集合中没有某个字段的数据.
先插入两条数据:
>db.col.insert({name: '张三', age: 18) >db.col.insert({name: '李四')
现在需求查询没有 age 字段的数据, 方法如下:
>db.col.find({'age': {$exists:false}})
复合条件查询
OR 条件
OR 条件语句使用了关键字 $or, 语法格式如下:
>db.col.find( { $or: [ {key1: value1}, {key2:value2} ] } ).pretty()
IN 条件
in 条件语句, 也是一种或者逻辑, 使用了关键字 $in, 但它与 or 不同, or 是在不同的 field 之间或者, 而 in 是在同一个 field 间或者, 并且支持对数组型元素进行查询
>db.col.find({key1: {$in: [value1, value2]}}).pretty()
匹配 key1 的值为 value1 或者 value2 的元素, 或者匹配包含有 value1 / value2 的数组元素.
AND 条件
OR 条件语句可以使用了关键字 $and, 也可以直接在条件 document 中可以传入多个键(key), 每个键(key)以逗号隔开.
>db.col.find( { $and: [ {key1: value1}, {key2:value2} ] } ).pretty() >db.col.find({key1:value1, key2:value2}).pretty()
ALL 条件
ALL 条件用来对数组中的元素进行全匹配, 使用了关键字 $all.
>db.col.find({key1: {$all: [value1, value2]}}).pretty()
首先, key1 要是个数组, 如 [value1, value2 …]
该语句匹配同时包含元素 value1 和 value2 的数组.
正则查询
MongoDB 的查询也是支持正则的, 但是正则查询的效率是比较低的, 建议只对建立了索引的 field 进行正则.
投影
投影意思是只查询必要的字段而不是查询所有的字段, 例如一个文档有 5 个字段, 需要显示的只有 3 个, 此时就可以用投影.
find() 方法的第二个可选参数是要投影的字段列表, 在该参数中设置的字段列表值 1 或 0
- 1 用来显示字段
- 0 用来隐藏字段
语法: find() 方法具有投影基本语法如下
db.COLLECTION_NAME.find({}, {KEY1: 1, KEY1: 0})
请注意 _id 字段始终显示, 如果不想这个字段, 那么需要将其设置为 0:
db.COLLECTION_NAME.find({}, {KEY: 1, _id: 0})
分页
MongoDB 的分页功能需要用到两个方法: Limit() 和 Skip()
Limit()
limit() 方法接受一个数字参数, 该参数指定读取的记录条数.
db.COLLECTION_NAME.find().limit(number)
Skip()
skip() 方法用来跳过指定数量的数据, skip() 方法同样接受一个数字参数作为跳过的记录条数
db.COLLECTION_NAME.find().skip(number)
配合 Limit() 和 Skip() 就能实现分页查询的功能, 例如每页面显示 10 条数据, 想显示第 5 页的数据:
db.COLLECTION_NAME.find().skip(4 * 10).limit(10)
排序
命令格式:
db.COLLECTION_NAME.find().sort({KEY: 1})
Key 可以设为 1 或者 -1, 1 用于升序排列, 而 -1 用于降序.
注意: 排序是一个耗性能的操作, 建议只对建立了索引的 key 进行排序.