Kaze
Kaze
Published on 2022-05-14 / 47 Visits
0
0

mongoDB

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 可取的值有

描述
Pointcoordinates 字段只有一个坐标
LineStringcoordinates 字段有两个坐标
Polygoncoordinates 字段会有两个以上坐标

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 执行的操作就是先查询符合我们查询条件的数据再进行去重操作。

image-20220512230458325

distinct 的查询结果的类型是数组,所以可以直接以 JSON 格式打印,以及打印长度。

聚合管道

聚合管道是将文档放入多个阶段组成的管道,每个阶段可以将结果进行处理(分组,过滤等)得到的数据可以直接输出也可以作为下一个阶段的数据源,类似于java的streamAPI。

MongoDB 的聚合用的是 aggregate() 方法:

image-20220512231538433
常用的聚合操作符
$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>指定的字段不显示,其他都显示,注意和第一个用法会产生冲突
image-20220513223136629

MongoDB 的“加减乘除”运算,分别为$add(+)$subtract(-)$multiply(*)$divide(/)

$match

$match的作用和find()一样。具体用法为: { $march : { <query> } }

$group
image-20220513225858612
常用表达式操作符简述
$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 的工作过程

  1. MapReduce 是由 Map 和 Reduce 组成。
  2. Map 负责把数据集进行切片
  3. Reduce 负责把切片的数据汇总、计算

MapReduce在MongoDB中的应用

db.collection.mapReduce(
   function() {emit(key,value);}, //map 函数
   function(key,values) {return reduceFunction}, //reduce 函数
   {
      out: <输出的临时表>,
      query: <查询条件>,
      sort: <排序条件>,
      limit: <限制数量>,
      finalize: <最后执行的函数>
   }
)
常用表达式操作符简述
mapJavaScript 函数,将输入的文档通过 key 进行分组,生成键值对,是 reduce 函数的入参
reduceJavaScript 函数,对 map 的输出结果进行操作(将 key-values 中的 values 做操作)。 注意 reduce 在v4.2.6 版本不能返回数组
out统计结果存放集合(不指定的话会存储在临时表中,与客户端断开连接后数据会丢失)
query查询条件(执行在 map 函数之前,可以不写)
sort排序(执行在 map 函数之前,可以不写)
limit限制向 map 函数输入值的数量 (执行在 map 函数之前,可以不写)
finalize可以对 reduce 函数结果进一步修改 (可以不写)

Comment