MongoDB学习 自我学习

##mongo学习,最近项目中要存储一些非结构化的数据,因此需要使用到MongoDB。非结构化数据如:物联网项目中的设备模型(属性、服务、事件)每个设备或者每种设备都完全不一样,使用mysql估计需要6-7张表,为了存储、查询方便,我们采用MongoDB。

一、 MongoDB优势

MongoDB优势:
1: 副本集Replication(类似主从),但可以自动容灾,容灾是自动选举一个新的节点做主节点(primary、secondary)。主写,记录日志oplog,从库从oplog读取信息,写入从库。
2:分片sharding:当一台机器,难以存储海量数据,可以通过分片,把数据分散到不同的机器上面。副本、分片,让MongoDB天生可靠、负载更简单,其他数据库需要额外负载的中间件才能完成。
3:不需要定义表结构,直接存储。表设计,可以使用 关系型数据库设计完成。
4:表查询有join 或者 复杂查询 或者 强事物的 不建议使用MongoDB。
5: 支持TB、PB级别的数据,有索引的字段不必mysql、没有索引的全面胜出mysql
MongoDB缺点:
1: 占用空间大
2: 开发 运维使用工具少; Navicat for mongo, 建议先创建一个新的db 进行操作,不要用内置库。
  1. 默认端口 27017, MongoDB经常遭到黑客入侵,我们该端口47071
  2. 自带数据库 local、config、admin, 一般不要使用默认自带数据库。比如使用local, 如果是副本集的情况,故障local数据里面会丢失。

参考: [1、mongodb中的admin数据库和local数据库(https://www.cnblogs.com/MyOnlyBook/articles/6201391.html)
参考:[2、什么是MongoDB ]
参考:Mongodb集群搭建的三种方式

1. MongoDB简单命令

 1: MongoDB默认有三个内置库,我们自己创建新库使用
 2:查询库中的数据
 3:添加数据库
>  mongo -version; #4.x 目前使用MongoDB4.x
> mongo # 如: mongo --port=47071 使用MongoDB直接进入MongoDB;mongoDB 没有root用户,只有能管理用户的用户userAdminAnyDatabase;  如果有授权,必须执行下面自己授权。 如果有其他设置,请 mongo --help ,加上指定参数。
> use admin;  #必须切换admin, 然后 show dbs;发现没有任何表,说明,开启密码,必须登录。
> db.auth('admin','admin@123xX.`1];'); #如果开启密码,这里必须授权登录。 前面是账号、后面是密码; 返回1,登录成功;  
#db.auth('iotMongoUserX','.123aB.iotMongoUserXpWD');
>  show dbs; #查看所有数据库,登录之后就可以查看所有db了。
>  show users; #查看当前库中MongoDB的所有用户。普通账号,查看会报错。
# mongo 创建用户:
use admin;
db.createUser(
  {
    user: "admin",
    pwd: "admin@123xX.`1];",
    roles: [ { role: "userAdminAnyDatabase", db: "admin" }, "readWriteAnyDatabase" ]
  }
)
)
# 指定数据库,重新登录之后,就只能看到自己的两个数据库,其他配置库和系统库都看不到的。
db.createUser(
  {
    user: "iotMongoUserX",
    pwd: ".123aB.iotMongoUserXpWD",
    roles: [ { role: "readWrite", db: "iot_gateway_mongo,iot_platform_mongo" },
             { role: "read", db: "testMongoDb" } ]
  }
);
# 修改用户角色、密码
db.updateUser(
   "<username>",
   {
     customData : { <any information> },
     roles : [
               { role: "<role>", db: "<database>" } | "<role>",
               ...
             ],
     pwd: "<cleartext password>"
    },
    writeConcern: { <write concern> }
)

#删除用户:
db.dropUser('mongoIotuser');
# 查看所有用户,先切换到admin
show users;
#创建数据库 & 插入测试数据 和 查看
>  use testdb; #如果不存在,则会自动创建数据库。要显示需要插入数据;《testdb》
>  db.createCollection("students"); #创建集合students,当然也可以不创建,不存在会生成。
>  show collections; #查看集合
>  db.students.insert({"name":"张三"}); #创建一个文档《students》
>   db.students.find().pretty(); #查询文档《students》中数据
>   db.students.drop(); #删除整个集合;db.getCollection('RunLog-mw-airconditioning-hailin').drop();#如果有特殊字符,就这样处理
>   

MongoDB用户和密码登录
MongoDB3.4开启用户验证、设置远程连接及更改数据存储路径
Mongodb 开启用户名密码访问控制

2 centos7 手工 安装使用

Centos7下yum安装mongodb - 自动yum 安装,手工下载官网太慢了

# yum 安装源,上面博文MongoDB版本是3.x,我们使用4.x; 别的全看上面的博客《Centos7下yum安装mongodb》
#vim /etc/yum.repos.d/mongodb-org-4.0.repo
[mngodb-org]
name=MongoDB Repository
baseurl=http://mirrors.aliyun.com/mongodb/yum/redhat/7Server/mongodb-org/4.0/x86_64/
gpgcheck=0
enabled=1
centos 查看MongoDB位置:whereis mongo 或者 find / -name "*mongo*"
centos 重启MongoDB: systemctl restart mongod.service  
centos 查看MongoDB状态: systemctl status mongod.service
目录1-命令目录:/usr/bin/mongo
目录2-数据目录:/var/lib/mongo  最好换一个目录,防止数据库目录把磁盘占满。eg: /usr/local2/mongo-data
目录3-备份目录,我们自己创建一个目录:/usr/local/mongodbbake/
目录4-配置目录:/etc/mongod.conf
#mongod.conf配置文件,我们对默认配置进行修改
# where to write logging data.
systemLog:
  logAppend: false #默认true,每次启动是追加日志;false: 是创建新日志文件。

port: 47071 #我们从27017改成47017,防止默认端口导致漏洞或者被黑客攻击
bindIp: 0.0.0.0  # 默认是:127.0.0.1 只有本机可以访问。 Enter 0.0.0.0,:: to bind to all IPv4 and IPv6 addresses or, alternatively, use the net.bindIpAll setting.; 默认绑定:127.0.0.1 就只能本地用户可以访问。0.0.0.0 允许所有人访问。
#security:
 # authorization: enabled  # 注释就是没密码,不注释就是开启密码
# MongoDB默认没有密码,我们一定要创建密码; 修改配置之后必须重启
systemctl restart mongod.service

MongoDB的数据备份与恢复

3. MongoDB 复制集

复制集类似主从,但是比主从要方便灵活,因此平时主要用的是复制集。MongoDB自带功能。

4. MongoDB 切片

MongoDB切片是基于复制集的,每个片都是一个复制集。因此搭建有两个分片MongoDB,就要4台服务器。

MongoDB水平分片集群学习笔记

mongodb切片集群架构图

5. rebo 3t 客户端工具

免费的MongoDB客户端工具;当然Navicat premium最新版也支持MongoDB

MongoDB时区问题 rebo 3t工具

6. mongodb 数据库连接池

Spring Boot 配置 Mongo DB 数据库连接池
# MongoDB 配置,指定数据库连接池;
# 连接池第三方的
### mongodb 配置,这里 MongoDB 没有设置账号和密码
  data:
    mongodb:
      # uri: mongodb://39.98.173.142 #无账号密码,禁止
      uri: mongodb://iotMongoUserX:.123aB.iotMongoUserXpWD@39.98.173.142:27017
      database: iot_platform_mongo  #指定数据库
      port: 27017
      option: # 每个主机的最小和最大连接数
        min-connection-per-host: 10
        max-connection-per-host: 150

Spring Boot 配置 Mongo DB 数据库连接池
mongodb 查看连接数和最大连接数
关于配置mongoDB连接池

7 MongoDB 定时备份

mongodb 定时备份 完美,文档非常好、定时备份、恢复都很详细。

# 目前都是通过服务器,没有账号密码恢复的。mongorestore 直接是shell命令; 不用进入MongoDB里面
# 说明:mongorestore 直接是一个shell命令,不用进入到 MongoDB shell控制台
# 这里没有密码注意,可能需要账号和密码; mongorestore --help可以查看
# 备份恢复示例1
# -h: 指定MongoDB数据库地址和端口; 默认本地
# –drop: 指定先删除表,后恢复。避免出现重复。可选
# -d : 指定恢复到那个一个数据库
# -u、-p同;默认无账号、密码
# --authenticationDatabase ,指定授权db: --authenticationDatabase=<database-name>  

 mongorestore -h localhost:47071  -d iot_platform_mongo  -u iotMongoUserX -p .123aB.iotMongoUserXpWD  /usr/local2/mongobake/iot_gateway_mongo/   --authenticationDatabase admin   
# 备份恢复示例2
 mongorestore -h localhost:47071  -d iot_platform_mongo  -u iotMongoUserX -p .123aB.iotMongoUserXpWD  /usr/local2/mongobake/iot_platform_mongo/   --authenticationDatabase admin
# --------------------------------------
# 备份导出示例1
# - h 指定主机端口,不指定默认,默认:27017
# -d 指定备份哪一个数据库,不指定备份所有数据库
# -u 指定账号
# -p 指定密码
# -o 指定导出位置 
 mongodump -h localhost:47071  -d iot_platform_mongo -u iotMongoUserX -p .123aB.iotMongoUserXpWD  --authenticationDatabase admin  -o /usr/local2/mongobake/baketest/

8 MongoDB 连接数

业界流传千万级别一下系统用mysql, 千万级别以上用MongoDB, 亿级别用hadoop。我们对其连接数看一下:

mongodb默认连接数

数据库名称默认连接数推荐连接数查询命令查询结果参考
MongoDB5万5万查询命令:db.serverStatus().connections;{ “current” : 86, “available” : 51114, “totalCreated” : 253, “active” : 1 }MongoDB查看当前连接数
MySQL1501000, 最大可连接数为16384show variables like '%max_connection%';‘max_connections’, ‘151’Mysql查看连接数(连接总数、活跃数、最大并发数)MySQL max_connections 总是 214 。不能设大了? max_connections = 214

9 定期清理日志数据

MongoDB数据定期清理,和删除指定月份数据。
MongoDB可以直接执行js文件,使用js很方便。
#!/bin/sh
#clear-mongo.sh
# 删除MongoDB日志表
# 参考:MongoDB 定时删除数据 https://blog.csdn.net/CL_YD/article/details/79461528
# 参考:shell脚本传递参数给mongo命令 https://blog.csdn.net/fangfu123/article/details/104748183
# 里面课加载js,什么东西都可以写了。非常棒

mongo 10.105.0.6:47071<<EOF
use admin;
db.auth("iotMongoUserX",".123aB.iotMongoUserXpWD");
show dbs;

db.getCollection('RunLog-mw-airconditioning-hailin').drop();
db.getCollection('RunLog-mw-automobile-baidu').drop();
db.getCollection('RunLog-mw-bus-wanfeng').drop();
db.getCollection('RunLog-mw-carpark-jieshun').drop();
db.getCollection('RunLog-mw-doorcontrol-jieshun').drop();
db.getCollection('RunLog-mw-elevator-taichuan').drop();
db.getCollection('RunLog-mw-face-wanfeng').drop();
db.getCollection('RunLog-mw-informationpublish-chinashine').drop();
db.getCollection('RunLog-mw-internetbehavior-sangfor').drop();
db.getCollection('RunLog-mw-light-kuaisicong').drop();
db.getCollection('RunLog-mw-soilirrigation-splant').drop();
db.getCollection('RunLog-mw-video-haikang').drop();
db.getCollection('RunLog-mw-visualintercom-taichuan').drop();
db.getCollection('RunLog-mw-wifi-huawei').drop();

db.getCollection('Services-mw-bus-wanfeng-feederBusBooking').find({"createTime": {lt:'2020-08-12 11:35:35'}}).forEach(function(item){db.getCollection('Services-mw-bus-wanfeng-feederBusBooking').remove({"_id":item._id})});


load("clear-mongo.js")

exit;
EOF


#下面操作动态变量的MongoDB命令
#   echo `date       -d "-1 days ago"       '+%Y-%m-%d %H:%M:%S'`  #获取一天前的时间
#MIN_DATE=`date       -d "-10 days ago"       '+%Y-%m-%d %H:%M:%S'`; #'2020-08-12 11:35:35';定义变量=和取值之间不能有空格;
//clear-mongo.js
//mongo 使用js写法清理或者删除部分数据
var mongo=new Mongo("10.105.0.6:47071");
var db=mongo.getDB("iot_gateway_mongo");

// 演示打印
printjson('---------开始打印-------');
printjson("数据条数:" + db.getCollection('Services-mw-carpark-jieshun-carout').count());

Date.prototype.Format = function (fmt) { // author: meizz
    var o = {
        "M+": this.getMonth() + 1, // 月份
        "d+": this.getDate(), // 日
        "h+": this.getHours(), // 小时
        "m+": this.getMinutes(), // 分
        "s+": this.getSeconds(), // 秒
        "q+": Math.floor((this.getMonth() + 3) / 3), // 季度
        "S": this.getMilliseconds() // 毫秒
    };
    if (/(y+)/.test(fmt))
        fmt = fmt.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length));
    for (var k in o)
        if (new RegExp("(" + k + ")").test(fmt)) fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
    return fmt;
};

Date.prototype.addDays = function(number) {
    var adjustDate = new Date(this.getTime() + 24 * 60 * 60 * 1000 * number);
    return adjustDate;
};


//获取30天前的时间 2020-08-12 11:35:35
var today30Ago =  new Date().addDays(10).Format("yyyy-MM-dd hh:mm:ss");
printjson("当前时间: " + today30Ago);

printjson("清理01-");
db.getCollection('Services-mw-bus-wanfeng-feederBusBooking').find({"createTime": {$lt: ''+ today30Ago +''}}).forEach(function(item){db.getCollection('Services-mw-bus-wanfeng-feederBusBooking').remove({"_id":item._id})});

printjson("清理02-");
db.getCollection('Services-mw-bus-wanfeng-feederBusTicket').find({"createTime": {$lt:''+ today30Ago +''}}).forEach(function(item){db.getCollection('Services-mw-bus-wanfeng-feederBusTicket').remove({"_id":item._id})});

printjson("清理03-");
db.getCollection('Services-mw-carpark-jieshun-carin').find({"createTime": {$lt:''+ today30Ago +''}}).forEach(function(item){db.getCollection('Services-mw-carpark-jieshun-carin').remove({"_id":item._id})});

printjson("清理04-");
db.getCollection('Services-mw-doorcontrol-jieshun-doorrecord').find({"createTime": {$lt:''+ today30Ago +''}}).forEach(function(item){db.getCollection('Services-mw-doorcontrol-jieshun-doorrecord').remove({"_id":item._id})});

printjson("清理05-");
db.getCollection('Services-mw-face-wanfeng-getReturnNumber').find({"createTime": {$lt:''+ today30Ago +''}}).forEach(function(item){db.getCollection('Services-mw-face-wanfeng-getReturnNumber').remove({"_id":item._id})});

printjson("清理06-");
db.getCollection('Services-mw-face-wanfeng-mqCousumer').find({"createTime": {$lt:''+ today30Ago +''}}).forEach(function(item){db.getCollection('Services-mw-face-wanfeng-mqCousumer').remove({"_id":item._id})});

printjson("清理07-");
db.getCollection('Services-mw-face-wanfeng-returnNumber').find({"createTime": {$lt:''+ today30Ago +''}}).forEach(function(item){db.getCollection('Services-mw-face-wanfeng-returnNumber').remove({"_id":item._id})});

printjson("清理08-");
db.getCollection('Services-mw-internetbehavior-sangfor-appRank').find({"createTime": {$lt:''+ today30Ago +''}}).forEach(function(item){db.getCollection('Services-mw-internetbehavior-sangfor-appRank').remove({"_id":item._id})});

printjson("清理09-");
db.getCollection('Services-mw-internetbehavior-sangfor-userRank').find({"createTime": {$lt:''+ today30Ago +''}}).forEach(function(item){db.getCollection('Services-mw-internetbehavior-sangfor-userRank').remove({"_id":item._id})});

printjson("清理10-");
db.getCollection('Services-mw-soilirrigation-splant-returnNumber').find({"createTime": {$lt:''+ today30Ago +''}}).forEach(function(item){db.getCollection('Services-mw-soilirrigation-splant-returnNumber').remove({"_id":item._id})});

printjson("清理11-");
db.getCollection('Services-mw-video-haikang-videoCatchcar').find({"createTime": {$lt:''+ today30Ago +''}}).forEach(function(item){db.getCollection('Services-mw-video-haikang-videoCatchcar').remove({"_id":item._id})});

printjson("清理12-");
db.getCollection('Services-mw-video-haikang-videoCatchface').find({"createTime": {$lt:''+ today30Ago +''}}).forEach(function(item){db.getCollection('Services-mw-video-haikang-videoCatchface').remove({"_id":item._id})});

printjson("清理13-");
db.getCollection('Services-mw-visualintercom-taichuan-returnNumber').find({"createTime": {$lt:''+ today30Ago +''}}).forEach(function(item){db.getCollection('Services-mw-visualintercom-taichuan-returnNumber').remove({"_id":item._id})});

10 定期拆分和清理日志

MongoDB日志默认在 /var/log/mongodb, 但是一直是追加,经常非常大,甚至上G,我们对日志进行分割 。

参考 MongoDB日志过大怎么办?

#!/bin/bash
#mongo-logRotate.sh
#Rotate the MongoDB logs to prevent a single logfile from consuming too much disk space.
#拆分MongoDB日志,避免日志文件过大

mongo 10.105.0.6:47071<<EOF
use admin;
db.auth("iotMongoUserX",".123aB.iotMongoUserXpWD");

db.runCommand({logRotate:1});

show dbs;
exit;
EOF

编辑定时cron: crontab -e,填入内容:0 5 * * * /usr/local/sh/mongo-logRotate.sh > /var/null #MongoDB logRotate定期拆分,保存。

11 mongo定时任务列举

# crontab -e 编辑MongoDB的相关定时任务
0 4 * * *  /usr/local/sh/mongod_bak.sh   > /var/null #mongo的的备份
0 5 * * *  /usr/local/sh/mongo-logRotate.sh  > /var/null #MongoDB日志拆分
*/1 * * * *  /usr/local/sh/mongo-auto-restart.sh   > /var/null #mongodb 自动重启

12 mongo 原始方式启动

参考 - 原始方式安装:MongoDB的启动与停止
参考-启动报错 搭建Mongodb过程中报错:child process failed, exited with error number 48、1、100

#后台启动
mongod --fork 
# 启动命令
 mongod -f /etc/mongod.conf 
# 查看服务
 ps aux|grep mongo
# MongoDB禁止使用kill -9关闭 

二、Mongodb 使用dokcer 安装

2.1 docker 安装单机版

dockerhub里面的MongoDB安装资料,特别详细,直接看docker hub 官网资料。
2.1.1 Start a mongo server instance
# 这里安装一个MongoDB,指定名称叫做mongo;映射外部端口:27017(前外网);指定账号、密码、指定数据库目录;
docker run -d --name mongo-some \
	-p 27017:27017 \
	-e MONGO_INITDB_ROOT_USERNAME=mongoadmin \
	-e MONGO_INITDB_ROOT_PASSWORD=secret9527 \
	-v /usr/local/mongodb/datadir:/data/db \
	mongo
2.1.2 Creating database dumps
# docker中对MongoDB进行定期导出,导出成归档模式,然后进行gzip压缩
# 指定导出数据库、指定账号密码、指定压缩方式
# 直接把容器内文件,导出到容器外的主机上面。
	docker exec mongo-some sh -c 'exec mongodump -d admin -u mongoadmin -p secret9527 --archive --gzip ' > /usr/local/mongodb/mongobake/all-collections.archive.gzip

#恢复,只能把文件copy到容器内部,在容器内部执行了
mongorestore -h 127.0.0.1:27017 --gzip --archive=/***/***/Desktop/test.archive

三、Mongodb 查询

MongoDB项目中使用的时候,常见操作有增删改查、分页、分组、聚合等。

MySQL与MongoDB查询互转

3.1 简单列表查询find、count

# 最简单查询示例:
mongoTemplate.find(mongoQuery, xxxxxInstanceVo.class);//查询列表
mongoTemplate.count(mongoQuery, xxxxxInstanceVo.class);//查询总条数
mongoTemplate.insert(iotEquitpmentInstance);//插入数据,默认是实体名称
mongoTemplate.insert(o, "Services-collectionName-type");//插入数据&指定MongoDB的document名称; 新增是insert
mongoTemplate.save(dests)//save是update
//更新,也可以是:
Update update = Update.update("status", status);
                mongoTemplate.updateMulti(query, update, IotBusLinkageTriggerVo.class);
                

3.2 Criteria 使用

Criteria.where("crossTime").gte(beginDate).lte(endDate);
 Criteria.where("personName").is("张三")
                            .and("sex").is(o.get("female"))
                            .and("age").in(1,2,3)
                            .and("birthday").gte("2000-01-01 00:00:00").lte("2020-12-31 23:59:59")
                            .and("hometown1").regex(Pattern.compile("^.*" + "陕西省" , Pattern.CASE_INSENSITIVE))
                            .and("hometown2").regex(Pattern.compile("陕西省" + ".*$", Pattern.CASE_INSENSITIVE))
                            .and("hometown3").regex(Pattern.compile("^.*" + "陕西省" + ".*$", Pattern.CASE_INSENSITIVE))
                    ;

3.3 分组 group 使用

MongoDB的聚合操作,可以同时对多个字段进行聚合

mongoTemplate聚合操作

 public List<IotEquitpmentInstanceVo> groupByFloorId(Map<String, Object> params, List<String> fieldsObject, String... groupByName) {
        //1: 第一步分组(多个字段分组)获取到所有的分组的设备的集合
        Criteria criteria =  MongoQuery.toCriteria(params);
        StringBuilder reduceFunctionStr = new StringBuilder("id:doc._id,name:doc.name,");
        for (int i = 0; fieldsObject != null && i < fieldsObject.size(); ++i) {
            reduceFunctionStr.append(fieldsObject.get(i)).append(":").append("doc.").append(fieldsObject.get(i));
            if (i != fieldsObject.size() - 1) {
                reduceFunctionStr.append(",");
            }
        }
        # 分组,可以支持多个字段
        GroupBy groupBy = GroupBy.key(groupByName).initialDocument("{ collectionFirst: [], total: 0 }").reduceFunction("function (doc,prev){prev.total+=1,  prev.total <= 1 ? prev.collectionFirst.push({" + reduceFunctionStr.toString() +"}) : '';}");

        String documentName = StringUtils.uncapitalize(IotEquitpmentInstanceVo.class.getSimpleName());
        GroupByResults<IotEiGroupByFloorIdANdSiIdVo> groupByResults =  mongoTemplate.group(criteria, documentName, groupBy, IotEiGroupByFloorIdANdSiIdVo.class);

        //2: 把每组的第一个设备封装到集合里面
        List<IotEquitpmentInstanceVo> instanceVos = new ArrayList<>();
        for (IotEiGroupByFloorIdANdSiIdVo groupByResult : groupByResults) {
            instanceVos.addAll(groupByResult.getCollectionFirst());
        }
        return  instanceVos;
    }
//IotEiGroupByFloorIdANdSiIdVo.java

@Getter
@Setter
@ApiModel(description = "eiid 设备的聚合查询vo")
public class IotEiGroupByFloorIdANdSiIdVo {
    @ApiModelProperty("设备位置-楼层")
    private String floorId;

    @ApiModelProperty("别称:systemInstanceId = siId, 系统id")
    private String sysModelInstancId;

    @ApiModelProperty("设备集合的第一个设备")
    private List<IotEquitpmentInstanceVo> collectionFirst;

    @ApiModelProperty("该分组的中的设备总数")
    private int total;
}

3.4 聚合操作Aggregation.newAggregation

mongo里面可以group之后进行sum、avg这种

参考:mongoTemplate.aggregate()聚合查询

    public List<StatisticalEntity> statistics(String beginDate, String endDate, int interceptions, Long tenantId) {
        //1: 查询条件
        Criteria criteria = Criteria.where("tenantId").is(tenantId + "");
        Aggregation aggregation5 =
                Aggregation.newAggregation(
                        
//1: match是查询条件                        
//2: project是增加或许删除参数
//3: group、count、as:分组 求和 起别名
Aggregation.match(Criteria.where("crossTime").gte(beginDate).lte(endDate)),
                        Aggregation.match(criteria),
                        Aggregation.project()
                                .and("crossTime").substring(0, interceptions).as("day"),
                        Aggregation.group("day")
                                .count().as("num"),
                        Aggregation.sort(new Sort(new Sort.Order(Sort.Direction.ASC, "_id"))));
        AggregationResults<StatisticalEntity> outputTypeCount5 =
                mongoTemplate.aggregate(aggregation5, "Services-mw-doorcontrol-jieshun-doorrecord", StatisticalEntity.class);
        return outputTypeCount5.getMappedResults();
    }

3.5 关联查询、关联统计

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Dazer007

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值