概述

数据存储是为了可查询,统计。若数据只需存储,不需要查询,这种数据也没有多大价值

本篇介绍Mongodb

  • 聚合查询(Aggregation)
  • 固定集合(Capped Collections)

准备工作

准备10000条数据

var orders = new Array();
for (var i = 10000; i < 20000; i++) {
orders[i] = {
orderNo: i + Math.random().toString().substr(3, 3),
price: Math.round(Math.random() * 10000) / 100,
qty: Math.floor(Math.random() * 10) + 1,
orderTime: new Date(new Date().setSeconds(Math.floor(Math.random() * 10000)))
};
}
db.order.insert(orders);

聚合查询

Mongodb的聚合函数操作都在db.collection.aggregate,通过定义聚合管道(一组规则),达到分组,统计等功能,下面介绍常用的几种聚合函数

分组管道($group)

格式

{
$group:
{
_id: <expression>, // Group By Expression
<field1>: { <accumulator1> : <expression1> },
...
}
}

_id 是分组字段,若指定_id = null 或常量字段,就是将整个结果集分组。

分组统计字段格式{ <accumulator1> : <expression1> }

累计器操作(Accumulator Operator)参考Accumulator Operator

假设现在需要统计每天每个小时的订单总价格,平均价格,最大,最小,总订单数等

db.order.aggregate([
{
$group: {
//分组字段,这里用到$dateToString格式化,这里按小时统计
_id: { $dateToString: { format: "%Y-%m-%d %H", date: "$orderTime" } },
//总价格
totalPrice: { $sum: "$price" },
//分组第一个订单
firstOrder: { $first: "$orderNo" },
//分组最后一个订单
lastOrder: { $last: "$orderNo" },
//平均价格
averagePrice: { $avg: "$price" },
//最大价格
maxPrice: { $max: "$price" },
//最小价格
minPrice: { $min: "$price" },
//总订单数
totalOrders: { $sum: 1 },
}
}
])

返回结果

{ "_id" : "2020-04-12 15", "totalPrice" : 172813.68, "firstOrder" : "10000263", "lastOrder" : "19999275", "averagePrice" : 49.20662870159453, "maxPrice" : 99.94, "minPrice" : 0.01, "totalOrders" : 3512 }
{ "_id" : "2020-04-12 13", "totalPrice" : 80943.98, "firstOrder" : "10004484", "lastOrder" : "19991554", "averagePrice" : 50.780414052697616, "maxPrice" : 99.81, "minPrice" : 0.08, "totalOrders" : 1594 }
{ "_id" : "2020-04-12 14", "totalPrice" : 181710.15, "firstOrder" : "10001745", "lastOrder" : "19998830", "averagePrice" : 49.76996713229252, "maxPrice" : 99.93, "minPrice" : 0.01, "totalOrders" : 3651 }
{ "_id" : "2020-04-12 16", "totalPrice" : 63356.12, "firstOrder" : "10002711", "lastOrder" : "19995793", "averagePrice" : 50.97032984714401, "maxPrice" : 99.95, "minPrice" : 0.01, "totalOrders" : 1243 }

筛选管道($match)

格式

{ $match: { <query> } }

这个比较简单,就是筛选数据

假设我现在需要筛选金额在(10,15)之间的

db.orders.aggregate([
{
$match: {
"price": { $gt: 10, $lt: 15 }
}
}
])

排序管道($sort)

格式

{ $sort: { <field1>: <sort order>, <field2>: <sort order> ... } }

指定字段排序,1:升序,-1:倒序

限制条数($limit)

格式

{ $limit: <positive integer> }

Mongodb的聚合管道有很多,具体不一一列出,参考Aggregation Pipeline Stages — MongoDB Manual

带有(aggregation)就是都可以用于聚合管道

说了那么多,其实都没有使用Mongodb聚合函数最强大的功能,就是组合管道使用,查询我们需要数据,因为Mongodb提供的聚合管道函数非常多,所以组合起来使用是非常强大。

值得注意是管道的顺序,Mongodb是按你定义的顺序,将每一步执行的结果集传给下一个管道处理,输出是最后一个管道的结果集,所以不同的管道顺序会有可能得到不是预期的结果,甚至报错(这种情况报错甚至比得到不是预期的结果可能还好)

假设现在按每天小时统计符合下列条件的订单
  • 订单金额大于10元 小于 50元 && 数量小于等于5 and
  • 去掉金额最小的50条订单 && 去掉金额最大的50条订单 and
  • 统计每个小时内订单数量,订单金额
  • 按订单金额升序输出
db.order.aggregate([
{
$match: { "price": { $gt: 10, $lt: 50 }, "qty": { $lte: 5 } }
},
{
$sort: {
"price": -1
}
},
{
$skip: 50
},
{
$sort: {
"price": 1
}
},
{
$skip: 50
},
{
$group: {
_id: { $dateToString: { format: "%Y-%m-%d %H", date: "$orderTime" } },
totalPrice: { $sum: "$price" },
totalOrders: { $sum: 1 } }
},
{
$sort: {
"totalPrice": 1
}
}
])

解决思路

  1. 筛选符合条件的记录($match)
  2. 按金额倒序($sort:-1)
  3. 跳过金额最大的50条记录($skip:50)
  4. 按金额升序($sort:1)
  5. 跳过金额最小的50条记录($skip:50)
  6. 按每天每小时统计($group)
  7. 统计结果总金额升序($sort:1)

固定集合

概述

capped-collection are fixed-size collections that support high-throughput operations that insert and retrieve documents based on insertion order. Capped collections work in a way similar to circular buffers: once a collection fills its allocated space, it makes room for new documents by overwriting the oldest documents in the collection.

从上面定义可以看出固定集合具有几个特性

  • 固定大小
  • 高吞吐量
  • 根据插入顺序检索文档
  • 超过限制大小覆盖旧的文档

根据固定集合特性,固定集合适合用于以下场景

  • 只需保留最近的日志查询系统
  • 缓存数据(热点数据)
  • 等等

固定集合限制

  • 固定集合的大小创建之后不能修改
  • 不能删除固定集合里的文档,只能删除集合再重新建固定集合
  • 固定集合不能使用固定分区
  • 聚合管道$out不能使用在固定集合

固定集合使用

1. 创建固定集合

db.createCollection("log", { capped : true, size : 4096, max : 5000 } )
字段 必须 说明
capped 是       是否创建固定集合
size 固定集合大小,单位:字节
max 文档数量大小限制

size 和 max 是或关系,超出其中一个限制都会覆盖旧文档

2. 检查集合是否固定集合

db.collection.isCapped()

3. 将一个非固定的集合转换固定集合

db.runCommand({"convertToCapped": "mycoll", size: 100000});

测试固定集合

1. 超过限制文档数

// 1. 创建固定集合,大小1M,最大文档数量10
db.createCollection("log", { capped: true, size: 1024 * 1024, max: 10 }); // 2. 插入200条数据
for (var i = 0; i < 200; i++) {
db.log.insertOne({
"_id": i + 1,
"userId": Math.floor(Math.random() * 1000),
"content": "登录" + ("0000" + i).slice(-4),
"createTime": new Date(),
});
}

再查询现在Mongodb存储情况

db.log.stats()

可以看出每个对象都是占有78个字节,因为字段都是定长的

2. 验证操作存储大小

If the size field is less than or equal to 4096, then the collection will have a cap of 4096 bytes. Otherwise, MongoDB will raise the provided size to make it an integer multiple of 256.

如果size的字段设置小于4096,Mongodb将会提供一个256的倍数的数据存储大小

假设256的大小,256 / 78 = 3.282051282051282,应该能存3个文档

// 1. 删除之前固定集合
db.log.drop(); // 2. 创建固定集合,size < 78 , 验证是否创建一个256的大小
db.createCollection("log", { capped: true, size: 78 }); // 2. 插入200条数据
for (var i = 0; i < 200; i++) {
db.log.insertOne({
"_id": i + 1,
"userId": Math.floor(Math.random() * 1000),
"content": "登录" + ("0000" + i).slice(-4),
"createTime": new Date(),
});
}

查看集合统计

db.log.stats()

可以看出log集合使用了234个字节(78 * 3),也即3个文档的大小,最大能使用大小是256

3. 查询固定集合

Mongodb若没指定排序字段,是按存入顺序检索,可以使用.sort( { $natural: -1 } )改变输出顺序

db.log.find({}).sort( { $natural: -1 } )

4. 将非固定集合转换固定集合

将order转换试试

db.runCommand({"convertToCapped": "order", size: 8096});

查看order集合统计

只剩下90条数据

转发请标明出处:https://www.cnblogs.com/WilsonPan/p/12692642.html

【Mongodb】聚合查询 && 固定集合的更多相关文章

  1. MongoDB聚合查询及Python连接MongoDB操作

    今日内容概要 聚合查询 Python操作MongoDB 第三方可视化视图工具 今日内容详细 聚合查询 Python操作MongoDB 数据准备 from pymongo import MongoCli ...

  2. mongodb聚合查询-aggregate

    Mongodb-aggregate 在工作中经常遇到一些mongodb的聚合操作,和mysql对比起来,mongo存储的可以是复杂的类型,比如数组,字典等mysql不善于处理的文档型结构,但是mong ...

  3. MongoDB 聚合查询报错

    1.Distinct聚合查询报错 db.users.distinct("uname") db.runCommand({"distinct":"user ...

  4. MongoDB聚合查询

    1.count:查询记录条数 db.user.count() 它也跟find一样可以有条件的 db.user.count({}) 2.distinct:用来找出给定键的所有不同的值 db.user.d ...

  5. mongodb 聚合查询

    操作符介绍: $project:包含.排除.重命名和显示字段 $match:查询,需要同find()一样的参数 $limit:限制结果数量 $skip:忽略结果的数量 $sort:按照给定的字段排序结 ...

  6. 记一次mongodb聚合查询

    先说一下场景,产品中用到了简单的表单构造器,开始提供了一系列的控件,例如单行文本框.多行文本框.单选.复选.时间等,之后你可以拖拽控件自己组装你想要的表单……网上有很多的表单构造器,这里就不细说了,可 ...

  7. MongoDB的学习和使用(固定集合[Capped Collections])

    MongoDB 固定集合(Capped Collections) MongoDB 固定集合(Capped Collections)是性能出色且有着固定大小的集合,对于大小固定,我们可以想象其就像一个环 ...

  8. MongoDB 固定集合

    MongoDB 固定集合(Capped Collections)是性能出色且有着固定大小的集合,对于大小固定,我们可以想象其就像一个环形队列,当集合空间用完后,再插入的元素就会覆盖最初始的头部的元素! ...

  9. mongoDB 固定集合(capped collection)

    固定集合(Capped Collection)是一种尺寸固定的“循环”集合,可提供高效的创建.读取.删除等操作.这里所指的“循环”的意思是,当分配给集合的文件尺寸耗尽时,就会自动开始删除最初的文档,不 ...

随机推荐

  1. Mac Maven安装与配置

    下载 官网地址:http://maven.apache.org/download.cgi 配置环境变量 总步骤 编辑.bash_profile文件 vim ~/.bash_profile 配置mave ...

  2. [日志分析]Graylog2进阶之获取Nginx来源IP的地理位置信息

    如果你们觉得graylog只是负责日志收集的一个管理工具,那就too young too naive .日志收集只是graylog的最最基础的用法,graylog有很多实用的数据清洗和处理的进阶用法. ...

  3. 初识Flask、快速启动

    目录 一.初识Flask 1.1 什么是flask? 1.2 为什么要有flask? 二.Flask快速启动 一.初识Flask 1.1 什么是flask? Flask 本是作者 Armin Rona ...

  4. Docker基本概念及架构

    一.Docker基本概念 Docker是一个开源的容器引擎,基于Go 语言并遵从 Apache2.0 协议开源.Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级.可移植的容器中,然后发布 ...

  5. 我用STM32MP1做了个疫情监控平台4—功能完善界面重新设计

    目录 前言 界面展示 新增功能 API 接口说明 多个接口数据的获取和解析 FontAwesome字体图标库的使用 代码下载 系列教程 @ 前言 之前我用STM32MP1和Qt实现了疫情监控平台,系列 ...

  6. Callable的Future模式

    一.线程实现方式 1.继承Thread类 2.实现Runnable接口 3.线程池 4.Callable 二.无论使用继承Thread类还是实现Runnable接口,还是使用线程池都没有办法解决2个问 ...

  7. Core3.1WebApi_ 同源策略_如何支持跨域(转载)

    原文:https://mp.weixin.qq.com/s/id3fOyGrZI9lLx7PKbVYlg

  8. SpringMvc @Validated注解执行原理

    @Validated和@Valid对比 Spring Validation验证框架对参数的验证机制提供了@Validated(Spring's JSR-303规范,是标准JSR-303的一个变种),j ...

  9. 【攻防世界】simple-unpack

    知识:upx脱壳 simple-unpack 难度系数: 3.0 题目来源: 暂无 题目描述:菜鸡拿到了一个被加壳的二进制文件 提示说有壳子:然后用PE分析发现是ELF upx的壳子

  10. 2020.3.23 模拟赛游记 & 题解

    这次的模拟赛,实在是水. 数据水,\(\texttt{std}\) 水,出题人水,做题人也水.??? 游记就说一句: 水. T1 metro 弱智题. 人均 \(100pts\). #pragma G ...