目录
什么是MongoDB?
MongoDB是一个文档数据库(以 JSON 为数据模型),由C++语言编写,旨在为WEB应用提供可扩展的高性能数据存储解决方案。
MongoDB是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。它支持的数据结构非常松散,数据格式是BSON,一种类似JSON的二进制形式的存储格式,简称Binary JSON ,和JSON一样支持内嵌的文档对象和数组对象,因此可以存储比较复杂的数据类型。Mongo最大的特点是它支持的查询语言非常强大,其语法有点类似于面向对象的查询语言,几乎可以实现类似关系数据库单表查询的绝大部分功能,而且还支持对数据建立索引。原则上 Oracle 和 MySQL 能做的事情,MongoDB 都能做(包括 ACID 事务)。
MongoDB与关系型数据库对比
MongoDB应用场景
-
游戏场景,使用 MongoDB 存储游戏用户信息,用户的装备、积分等直接以内嵌文档的形式存储,方便查询、更新;
-
物流场景,使用 MongoDB 存储订单信息,订单状态在运送过程中会不断更新,以MongoDB 内嵌数组的形式来存储,一次查询就能将订单所有的变更读取出来;
-
社交场景,使用 MongoDB 存储存储用户信息,以及用户发表的朋友圈信息,通过地理位置索引实现附近的人、地点等功能;
-
物联网场景,使用 MongoDB 存储所有接入的智能设备信息,以及设备汇报的日志信息,并对这些信息进行多维度的分析;
-
视频直播,使用 MongoDB 存储用户信息、礼物信息等;
-
大数据应用,使用云数据库MongoDB作为大数据的云存储系统,随时进行数据提取分析,掌握行业动态。
MongoDB语法
数据库操作
sql
#查看所有库
show dbs
# 切换到指定数据库,不存在则创建
use test
#如果指定的数据库不存在,MongoDB 会在插入第一条文档时自动创建它
db.myCollection.insertOne({ key: "value" })
# 删除当前数据库
db.dropDatabase()
集合操作
javascript
#查看集合
show collections
#创建集合
db.createCollection("emp")
#删除集合
db.emp.drop()
#删除当前数据库所有用户
db.dropAllUser()
安全认证
sql
# 设置管理员用户名密码需要切换到admin库
use admin
#创建管理员
db.createUser({user:"awei",pwd:"123456",roles:["root"]})
# 查看所有用户信息
show users
#删除用户
db.dropUser("awei")
常用权限
MongoDB插入指令
使用insertOne()或insertMany()方法插入文档。
javascript
// 插入一个文档
db.collection.insertOne({ key: value });
db.employees.insertOne({
"name": "John Doe",
"age": 30,
"salary": 50000.0
})
// 插入多个文档
db.collection.insertMany([{ key1: value1 }, { key2: value2 }]);
db.employees.insertMany([{
"name": "zhangsan",
"age": 30,
"salary": 5000.0
}, {
"name": "lisi",
"age": 25,
"salary": 2000.0
}])
MongoDB查询指令
javascript
// 查询所有文档
db.employees.find();
// 查询特定条件的文档,例如年龄为30的员工
db.employees.find({ "age": 30 });
// 以格式化的方式来显示所有文档
db.collection.find().pretty()
查询条件对照表
查询逻辑对照表
查询逻辑运算符
$lt: 存在并小于
$lte: 存在并小于等于
$gt: 存在并大于
$gte: 存在并大于等于
$ne: 不存在或存在但不等于
$in: 存在并在指定数组中
$nin: 不存在或不在指定数组中
$or: 匹配两个或多个条件中的一个
$and: 匹配全部条件
MongoDB更新指令
javascript
// 更新单个文档,将John Doe的薪水增加到60000.0
db.employees.updateOne({ "name": "zhangsan" }, { $set: { "salary": 60000.0 } });
// 更新多个文档,将所有年龄大于等于30的员工薪水增加到55000.0
db.employees.updateMany({ "age": { $gte: 25 } }, { $set: { "salary": 55000.0 } });
MongoDB删除指令
javascript
// 删除单个文档,删除名为John Doe的员工
db.employees.deleteOne({ "name": "zhangsan" });
// 删除多个文档,删除所有年龄小于25的员工
db.employees.deleteMany({ "age": { $lt: 25 } });
// 删除当前数据库
db.dropDatabase()
注意:deleteMany命令需要对查询范围内的文档逐个删除,如果希望删除整个集合,则使用drop命令会更加高效。
findOneAndDelete
deleteOne命令在删除文档后只会返回确认性的信息,如果希望获得被删除的文档,则可以使用findOneAndDelete命令。(每次只能删除一个,如果两个age=30的数据,一次删除一个)
javascript
db.employees.findOneAndDelete({age:30})
内嵌文档和数组
以book文档为例,一个文档中可以包含作者的信息,包括作者名称、性别、家乡所在地,一个显著的优点是,当我们查询book文档的信息时,作者的信息也会一并返回。
javascript
db.createCollection("books")
db.books.insert({
title: "时间简史",
author: {
name:"霍金",
gender:"男",
hometown:"英国"
}
})
查询霍金的作品
javascript
db.books.find({"author.name":"霍金"})
修改霍金的家乡所在地
javascript
db.books.updateOne({"author.name":"霍金"},{$set:{"author.hometown":"中国"}})
数组
javascript
db.books.updateOne({"author.name":"霍金"},{$set:{tags:["旅行","随笔","散文","爱情","文学"]}})
查询数组元素
javascript
# 会查询到所有的tags
db.books.find({"author.name":"霍金"},{title:1,tags:1})
#利用$slice获取最后一个tag
db.books.find({"author.name":"霍金"},{title:1,tags:{$slice:-1}})
数组末尾追加元素,可以使用$push操作符
javascript
db.books.updateOne({"author.name":"霍金"},{$push:{tags:"猎奇"}})
push操作符可以配合其他操作符,一起实现不同的数组修改操作,比如和each操作符配合可以用于添加多个元素
javascript
db.books.updateOne({"author.name":"三毛"},{$push:{tags:{$each:["伤感","想象力"]}}})
如果加上$slice操作符,那么只会保留经过切片后的元素
javascript
db.books.updateOne({"author.name":"三毛"},{$push:{tags:{$each:["伤感","想象力"],$slice:-3}}})
根据元素查询
javascript
#会查出所有包含伤感的文档
db.books.find({tags:"伤感"})
# 会查出所有同时包含"伤感","想象力"的文档
db.books.find({tags:{$all:["伤感","想象力"]}})
嵌套型的数组
数组元素可以是基本类型,也可以是内嵌的文档结构
javascript
{
tags:[
{tagKey:xxx,tagValue:xxxx},
{tagKey:xxx,tagValue:xxxx}
]
}
这种结构非常灵活,一个很适合的场景就是商品的多属性表示
一个商品可以同时包含多个维度的属性,比如尺码、颜色、风格等,使用文档可以表示为:
javascript
db.goods.insertMany([{
name:"羽绒服",
tags:[
{tagKey:"size",tagValue:["M","L","XL","XXL","XXXL"]},
{tagKey:"color",tagValue:["黑色","宝蓝"]},
{tagKey:"style",tagValue:"韩风"}
]
},{
name:"羊毛衫",
tags:[
{tagKey:"size",tagValue:["L","XL","XXL"]},
{tagKey:"color",tagValue:["蓝色","杏色"]},
{tagKey:"style",tagValue:"韩风"}
]
}])
当我们需要根据属性进行检索时,需要用到$elementMatch操作符:
javascript
#筛选出color=黑色的商品信息
db.goods.find({
tags:{
$elemMatch:{tagKey:"color",tagValue:"黑色"}
}
})
如果进行组合式的条件检索,则可以使用多个$elemMatch操作符:
javascript
# 筛选出color=蓝色,并且size=XL的商品信息
db.goods.find({
tags:{
$all:[
{$elemMatch:{tagKey:"color",tagValue:"黑色"}},
{$elemMatch:{tagKey:"size",tagValue:"XL"}}
]
}
})
固定(封顶)集合
创建固定集合
javascript
db.createCollection("logs",{capped:true,size:4096,max:10})
max:指集合的文档数量最大值,这里是10条
size:指集合的空间占用最大值,这里是4096字节(4KB)
这两个参数会同时对集合的上限产生影响。也就是说,只要任一条件达到阈值都会认为集合已经写满。其中size是必选的,而max则是可选的。
可以使用collection.stats命令查看文档的占用空间
javascript
db.logs.stats()
将普通集合转换为固定集合
javascript
db.runCommand({"convertToCapped": "mycoll", size: 100000})