MongoDB介绍
简介
MongoDB 是一个由 C++语言编写的、基于 分布式 文件存储的 开源 数据库系统 。
MongoDB的优势:
- 采用文档结构的存储方式
- 内置 GridFS,支持大容量的存储。
- 性能优越
文档操作
单个数据插入
创建数据库表:使用db.createCollection("表名")
来创建表
查看创建好的表:show collections
删除表:db.表名.drop()
插入单个数据:
db.表名.insertOne({
_id: '1',
name: '夏季气质碎花裙子夏装',
description: '2020夏天连衣裙',
crossedPrice: 699,
currentPrice: 198,
productTag: ['NEW', 'WOMEN'],
productType: 'CLOTHING',
gmtCreated: ISODate('2020-05-12T22:50:43.744+08:00'),
gmtModified: new Date(),
})
查询表中所有数据:db.表名.find({});
批量数据插入
插入多个数据:
db.表名.insertMany(
[ document1 , document2, ... ],
)
主键
指定 _id
时我们插入数据 _id
是 string 类型,如果没有指定_id 值时 MongoDB 会默认插入一条主键 id,它的默认类型是 ObjectId 类型。
ObjectId 是一个 24 位的字符串,每个字节两位十六进制数字。如:5ecbca5231522a48d43cd1a1
覆盖式插入
当我们给定对应的_id 的值时我们首先先去查询对应的数据值,然后用最新的数据值覆盖掉之前的数据值。
简单更新
db.ykd_product.updateOne(
{
name: '杰克琼斯运动寸衫',
},//需要查询的条件内容
{
$set: {
crossedPrice: 999,
currentPrice: 599,
},
},//需要更新的内容
true //upsert:如果不存在该数据则将该数据插入到数据库中
);
基本删除
db.ykd_product.deleteOne({
name:'阿迪达斯运动新款寸衫' //删除条件
})
文档查询
比较运算符
db.ykd_product.find({
productType: 'SHOE',
crossedPrice: { $gt: 1000 },
});
$gt
这个比较操作符,它表示大于的意思。
$gte
操作符实现了大于等于的操作。
in 关键字用法
db.ykd_product.find({
crossedPrice: { $in: [1299, 1599, 1199] },
});
//一次性将划线价是 1299、1599、1199 的商品查询出
$in
后面接入的是数组,里面可以存放各个要求的条件信息,这样在查询时只会查询出满足数组里面条件数据。
$nin
关键字用法正好和$in
用法相反,它这个正好是不满足数组里面的条件。
常见比较操作符
- $eq: equal 缩写,表示和条件值相等。
- $ne: not equal 缩写,表示和条件值不相等或者不存在。
- $gt: greater than 缩写 表示大于条件值。
- $gte: greater than or equal 缩写 表示大于或等于条件值。
- $lt: less than 缩写 表示小于条件值。
- $lte: less than or equal 表示小于或等于条件值。
- $in: 表示筛选出字段在数组中。
- $nin: not in 缩写,表示筛选出字段不在数组中。
逻辑操作符
AND操作符:
db.ykd_product.find({
$and: [
{ productType: 'SHOE' },
{
currentPrice: 999,
},
],
});
常用逻辑操作符
- $and:用于连接多个查询条件,表示查询的文档必须符合所有条件。
- $nor: 用于连接多个查询条件,表示查询的文档必须不符合所有条件。
- $or: 用于连接多个查询条件,表示查询的文档只满足其中一个条件即可。
- $not: 只可用于一个查询条件,表示查询的文档必须不符合该条件。
limit操作符
db.ykd_product.find({}).limit(5);
如果你不加 limit()的话每次系统会默认返回二十条数据。
正则表达式
db.ykd_product.find({
name: {
$regex: '运动鞋',
},
});
//模糊查询name中含有“运动鞋”关键字的数据
内嵌文档查询
内嵌文档
{
_id: 'YKD_0001',
payAmount: 299,
payNickName: '致远之道',
product: {
productName: '海澜之家夏季最新款寸衫',
currentPrice: 198.0,
productTag: ['NEW', 'WOMEN'],
productType: 'CLOTHING',
},
gmtCreated: new Date(),
gmtModified: new Date(),
}
内嵌文档查询
db.ykd_order.find({
'product.productName': '海澜之家夏季最新款寸衫',
});
性能优化
单字段索引
在我们数据库当中索引就是给一些指定数据做一个唯一的标示,并且会按一定的顺序规则排好序 当我们查询的时候就可以根据这个标示查询。
数据库_id
是文档的唯一标识,数据库在为了保证能根据文档 id 快速查询文档,MongoDB 默认会为集合创建_id 字段的索引。
// 按age字段创建升序索引(createIndex为创建索引
//参数为(1或-1)1代表按年龄升序排序,-1代表降序)
db.ykd_bank_accounts.createIndex( {age: 1} )
复合索引
查看索引:db.ykd_bank_accounts.getIndexes()
删除索引:db.ykd_bank_accounts.dropIndex("索引名")
复合索引是可以支持多个字段一起创建的索引,排序规则是先按第一个字段排序,第一个字段有相同的文档,再按第二个字段排序。
db.ykd_bank_accounts.createIndex( {age: 1, city: 1} )
复合索引支持匹配第一个字段的单字段查询。
全文本索引
全文本索引主要是用于查询文本文档,比如数据库存储的文章,可以快速的根据文章的某一字段查找。
创建 content 、name字段的全文本索引并设置权重值:
//创建索引
db.ykd_blog.createIndex(
{
'content': 'text', 'name': 'text'
},
{
'weights': { 'content': 1, 'name': 2 }
}
)
在查询的时候可以用 $text
操作符查询:
db.ykd_blog.find( {$text:{$search:'国家'}} )
//查询字段中包含“国家”关键字的文档
查询诊断优化
Mongodb 在查询时提供了 explain()方法, explain 操作提供了查询信息,使用索引及查询统计等。
db.ykd_bank_accounts.find({age: { $lt: 45 }}).explain('executionStats')
查看磁盘空间内存占用情况:
db.serverStatus().mem
在 Mongodb 中 删除表数据不释放占用的磁盘空间,需手动释放。
释放磁盘空间:
db.runCommand({closeAllDatabases:1})
地理空间数据
地理空间数据介绍
mongoDB为存储地理数据提供了特殊的存储格式,如:GeoJSON 对象、传统坐标对。
GeoJSON 对象
location: {
type: "Point",
coordinates: [120.212599, 30.290846]
}
type 可取的值有
值 | 描述 |
---|---|
Point | coordinates 字段只有一个坐标 |
LineString | coordinates 字段有两个坐标 |
Polygon | coordinates 字段会有两个以上坐标 |
1. Point(点,只需要一个坐标就可以定位(经纬度))
2. LineString(线 需要两个坐标来确定位置(两队经纬度))
3. Polygon(多边形 需要多个坐标来确定位置)
传统坐标
location: {
[<经度>, <纬度> ]
}
地理空间索引
2dsphere 索引
db.表名.createIndex({location:"2dsphere"})
查询杭州东站周围最少 100 米 最多 500000 米 以内的数据按从最近到最远的顺序排序
db.ykd_gd_map.find(
{
location:
{ $near:
{ //杭州东的坐标
$geometry: { type: "Point", coordinates: [ 120.212599, 30.290846 ] },
$minDistance: 100,
$maxDistance: 500000
}
}
}
)
查询杭州东站到东恒大厦的距离
db.ykd_gd_map.aggregate(
[
{
$geoNear: {
near: { type: "Point", coordinates: [ 120.212599, 30.290846 ] },
spherical: true,
query: { name: "东恒大厦" },
distanceField: "dist.location"//这个参数可以计算两者之间的距离
}
}
]
)
数据聚合
MongoDB 提供了三种方式执行聚合操作:单一的聚合命令、聚合管道、map-reduce 函数。
单一的聚合命令
count 用法
查询表数据量:db.表名.count();
查询符合条件的结果的数量:db.表名.find(query).count()
distinct 用法
distinct 执行的操作就是先查询符合我们查询条件的数据再进行去重操作。

distinct
的查询结果的类型是数组,所以可以直接以 JSON 格式打印,以及打印长度。
聚合管道
聚合管道是将文档放入多个阶段组成的管道,每个阶段可以将结果进行处理(分组,过滤等)得到的数据可以直接输出也可以作为下一个阶段的数据源,类似于java的streamAPI。
MongoDB 的聚合用的是 aggregate() 方法:

常用的聚合操作符
$limit、$skip、$sort
db.ykd_action_data.aggregate([
{ $sort: { data: -1 } },//将返回数据的顺序改为按照data字段降序排列
{ $skip: 0 },
{ $limit: 5 }
]);
$project
$project
可以改变原来的文档数据,处理成需要的数据。
{ $project: { <specification> } }
specification 的用法为:
用法 | 简述 |
---|---|
<字段名> : <1 或者 true> | 指定的字段显示 |
_id(主键,默认显示) : <0 或者 false> | 隐藏_id 字段 |
<字段名> : 表达式 | 使用表达式可以重命名字段,或对其值进行操作 |
<字段名> : <0 或者 false> | 指定的字段不显示,其他都显示,注意和第一个用法会产生冲突 |

MongoDB 的“加减乘除”运算,分别为$add(+)
,$subtract(-)
,$multiply(*)
,$divide(/)
$match
$match
的作用和find()
一样。具体用法为: { $march : { <query> } }
$group

常用表达式操作符 | 简述 |
---|---|
$sum | 计算总和,{$sum:1}表示返回每组对应多少个数据,如果是{$sum:'数据库字段'},则返回该字段的累加求和值 |
$avg | 求平均值 |
$min | 求最小值 |
$max | 求最大值 |
$push | 将结果放入到一个自定义的数组中 |
$first | 根据查询的文档顺序返回第一个数据 |
$last | 根据查询的文档顺序返回最后一个数据 |
$group 的_id 使用拼接字符串:
db.ykd_product.aggregate([
{ $sort: { currentPrice: 1 } },
{
$group: {
_id: { $concat: ['$productType', 'TEST'] },
cheapest: { $first: '$currentPrice' }
}
}
]);
$group 的_id 使用多个属性:
db.ykd_action_data.aggregate([
{
$group: {
_id: { date: '$date', accountId: '$accountId' },
process: { $push: '$process' }
}
}
]);
$group 的_id 为 null:
_id
为 null 就表示所有数据都在一个组里。
$count
统计商品当前价格大于 200 元的个数
db.ykd_product.aggregate([
{
$match: { currentPrice: { $gt: 200 } }
},
{ $count: 'number' }
]);
//number为自定义变量,自己可以自定义
多表关联查询
$lookup
{
$lookup:
{
from: <被关联的表>, //右集合
localField: <当前表的关联属性>, //左集合 join字段
foreignField: <被关联表的关联属性>, //右集合 join字段
as: <输出属性名> //新生成字段(类型array)
}
}
$unwind
unwind
用来将数组分片,取数组里的单个元素。如果$lookup关联了多个数据就不用分片了。
db.ykd_action_data.aggregate([
{
$lookup: {
from: 'ykd_accounts',
localField: 'accountId',
foreignField: '_id',
as: 'account'
}
},
{ $unwind: '$account' }
]);
Map Reduce
什么是MapReduce
MapReduce
是一种分布式的数据处理方式,以一种可靠的方式 并发 处理 TB 级别的数据,用来解决海量数据的计算问题。
MapReduce 的工作过程
- MapReduce 是由 Map 和 Reduce 组成。
- Map 负责把数据集进行切片
- Reduce 负责把切片的数据汇总、计算
MapReduce在MongoDB中的应用
db.collection.mapReduce(
function() {emit(key,value);}, //map 函数
function(key,values) {return reduceFunction}, //reduce 函数
{
out: <输出的临时表>,
query: <查询条件>,
sort: <排序条件>,
limit: <限制数量>,
finalize: <最后执行的函数>
}
)
常用表达式操作符 | 简述 |
---|---|
map | JavaScript 函数,将输入的文档通过 key 进行分组,生成键值对,是 reduce 函数的入参 |
reduce | JavaScript 函数,对 map 的输出结果进行操作(将 key-values 中的 values 做操作)。 注意 reduce 在v4.2.6 版本不能返回数组 |
out | 统计结果存放集合(不指定的话会存储在临时表中,与客户端断开连接后数据会丢失) |
query | 查询条件(执行在 map 函数之前,可以不写) |
sort | 排序(执行在 map 函数之前,可以不写) |
limit | 限制向 map 函数输入值的数量 (执行在 map 函数之前,可以不写) |
finalize | 可以对 reduce 函数结果进一步修改 (可以不写) |