mongoDB聚合函数

  1. 简单的分组
// 原生写法
db.deviceDataCollection.aggregate([
    {
        $match: {
            "tenantId": "1475652926985990144",
            "ts": {
                $gt: ISODate("2022-09-15T03:39:36Z")
            },
            "statusData": {
                "$ne": null,
                "$exists": true
            }
        }
    },
    {
        $sort: {
            "ts": - 1
        }
    },
    {
        $group: {
            _id:
			"$deviceId",
            ts: 
            {
                "$first": "$ts"
            }
        }
    },
    {
        $match: {
            "deviceId": "1"
        }
    },
    {
        $limit: 10
    }
])
		// java mongoTemplate
		Criteria criteria1 = new Criteria();
		Criteria criteria2 = new Criteria();
		
		Date endDate = new Date();
		Date startDate = new Date(endDate.getTime() - 24 * TIME_ONE_HOUR);
		criteria1.and("ts").gt(startDate).lt(endDate);
		criteria1.and("statusData").exists(true);
		criteria2.and("statusData.online").is("1");
		
		Aggregation agg = Aggregation.newAggregation(
		    Aggregation.match(criteria1),
		    Aggregation.sort(Sort.Direction.DESC, "ts"),
		    Aggregation.group("deviceId")
		        .first("_id").as("id")
		        .first("deviceId").as("deviceId")
		        .first("ts").as("ts")
		        .first("deviceManufacture").as("deviceManufacture")
		        .first("statusData").as("statusData"),
		    Aggregation.match(criteria2),
		    new SkipOperation((pageNum - 1) * pageSize),
		    Aggregation.limit(pageSize)
		);
		AggregationResults<DeviceDataEntity> aggregationResults = mongoTemplate.aggregate(agg, DEFAULT_COLLECTION_NAME, DeviceDataEntity.class);
		List<DeviceDataEntity> mappedResults = aggregationResults.getMappedResults();
  1. 对时间分组后并统计
// 原生写法
db.deviceDataCollection_1452589816758669312.aggregate([
    {
        $match: {
            "deviceId": "84fd27fffe71b688",
            "huatuoDeviceData.commandType": "Data",
            "huatuoDeviceData.sleepBandInfo.status": NumberInt("0"),
            "ts": {
                $gt: ISODate("2022-09-15T03:39:36Z"),
                $lt: ISODate("2022-09-15T03:39:36Z")
            }
        }
    },
    {
        $project: {
            date: {
                $dateToString: {
                    format: '%Y-%m-%d %H:%M',
                    date: '$ts',
                    timezone: "+08:00"
                }
            }
        }
    },
    {
        $group: {
            _id: 
            "$date",
            count: {
            // 1表示 出现一次 统计1次
                $sum: 1
            }
        }
    },
    {
        $match: {
            "count": {
                $gte: 10
            }
        }
    }
])
		// java mongodbTemplate
		String patternType = "%Y-%m-%d %H:%M";

        Criteria criteria1 = new Criteria();
        Criteria criteria2 = new Criteria();

        criteria1.and("deviceId").is(deviceId);
        criteria1.and("huatuoDeviceData.sleepBandInfo.status").is(0);
        criteria2.and("count").gte(10);

        Date startDate = string2Date(startTime, LocalDateTimeUtils.YYYY_MM_DD_HH_MM_SS);
        Date endDate = string2Date(endTime, LocalDateTimeUtils.YYYY_MM_DD_HH_MM_SS);
        if (startDate != null && endDate != null) {
            criteria1.and("ts").gte(startDate).lte(endDate);
        }

        Aggregation agg = Aggregation.newAggregation(
                Aggregation.match(criteria1),
                Aggregation.project("ts")
                        .and(DateOperators.DateToString.dateOf("ts").toString(patternType)).as("date"),
                Aggregation.group("date").count().as("count"),
                Aggregation.match(criteria2)
        );

        AggregationResults<DeviceDataEntity> aggregationResults =
                mongoTemplate.aggregate(agg, getCollectionName(tenantId), DeviceDataEntity.class);
        return aggregationResults.getMappedResults().size();

2.1. 分组后 结果是list 再聚合

db.getCollection("deviceDataCollection_1481152175999807489").aggregate([
    {
        "$match": {
            "deviceId": "JPUS000407",
            "commonDeviceData.extraCode": "291",
            "commonDeviceData.commonDeviceExtraData.status": "5",
            "commonDeviceData.commonDeviceExtraData.snoreTimes": {
                "$ne": 0
            },
            "ts": {
                "$gte": ISODate("2022-09-21T12:00:07Z"),
                "$lte": ISODate("2022-09-22T00:00:07Z")
            }
        }
    },
    {
        "$group": {
            "_id": {
                $dateToString: {
                    format: '%Y-%m-%d %H:%M:%S',
                    date: '$commonDeviceData.eventTime'
                }
            },
            "snore": {
                "$push": "$commonDeviceData.commonDeviceExtraData.snoreTimes"
            }
        }
    }
])

在这里插入图片描述
用 $push 结果会是list 无法统计 所以要给一个策略 取list里的哪一条

db.getCollection("deviceDataCollection_1481152175999807489").aggregate([
    {
        "$match": {
            "deviceId": "JPUS000407",
            "commonDeviceData.extraCode": "291",
            "commonDeviceData.commonDeviceExtraData.snoreTimes": {
                "$ne": 0
            },
            "ts": {
                "$gte": ISODate("2022-09-21T12:00:07Z"),
                "$lte": ISODate("2022-09-22T00:00:07Z")
            }
        }
    },
    {
        "$project": {
            date: {
                $dateToString: {
                    format: '%Y-%m-%d %H:%M:%S',
                    date: '$ts'
                }
            },
            "snore": 
            "$commonDeviceData.commonDeviceExtraData.snoreTimes",
            "deviceId": "$deviceId"
        }
    },
    {
        "$group": {
            "_id": "$date"
            ,
            "snore": {
                "$first": "$snore"
            },
            "deviceId": {
                "$first": "$deviceId"
            }
        }
    },
    {
        "$group": {
            "_id": "$deviceId",
            count: {
                "$sum": "$snore"
            }
        }
    }
])

用$first 取每组第一条 , 得到list, 再根据一个deviceId(相同的字段) 将list聚合成一条.

String patternType = "%Y-%m-%d %H:%M:%S";
        Criteria snoreCriteria = new Criteria();
        snoreCriteria.and("deviceId").is(deviceId);
        snoreCriteria.and("commonDeviceData.extraCode").is("291");
        if (startDate != null && endDate != null) {
            snoreCriteria.and("ts").gte(startDate).lte(endDate);
        }
        snoreCriteria.and("commonDeviceData.commonDeviceExtraData.snoreTimes").ne(0);
        Aggregation snoreAgg = Aggregation.newAggregation(
                Aggregation.match(snoreCriteria),
                Aggregation.project("commonDeviceData.eventTime", "commonDeviceData.commonDeviceExtraData.snoreTimes", "deviceId")
                        .and(DateOperators.DateToString.dateOf("ts").toString(patternType)).as("date")
                        .and("commonDeviceData.commonDeviceExtraData.snoreTimes").as("snore")
                        .and("deviceId").as("deviceId"),
                Aggregation.group("date")
                        .first("snore").as("snore")
                        .first("deviceId").as("deviceId"),
                Aggregation.group("deviceId")
                        .sum("snore").as("count")
        );
        AggregationResults<SleepDataEntity> snoreAggregationResults =
                mongoTemplate.aggregate(snoreAgg, getCollectionName(tenantId), SleepDataEntity.class);
        }

2.2 按半小时为一组,聚合数据

db.deviceDataCollection_1544241345868197888.aggregate([{
    $match: {
        "deviceId": "84fd27fffe7a277f",
        "$or": [{
            "commonDeviceData.commonDeviceExtraData.heartRate": {
                "$ne": "0"
            },
            "commonDeviceData.commonDeviceExtraData.status": {
                "$ne": "1"
            }
        }, {
            "commonDeviceData.commonDeviceExtraData.status": "1"
        }],
        "ts": {
            "$gte": ISODate("2023-02-22T12:00:00Z"),
            "$lte": ISODate("2023-02-23T23:59:59Z")
        }
    }
}, {
    $project: {
        "date": {
            "$subtract": [
                
                {
                    "$subtract": ["$ts", new Date("1970-01-01")]
                },
                {
                    "$mod": [
                        
                        {
                            "$subtract": ["$ts", new Date("1970-01-01")]
                        },
                        1000 * 60 * 30
                    ]
                }
            ]
        },
        "status": "$commonDeviceData.commonDeviceExtraData.status",
        "heartRate": {
            "$convert": {
                "input": "$commonDeviceData.commonDeviceExtraData.heartRate",
                "to": "int",
                "onError": 0,
                "onNull": 0
            }
        },
        "respiratoryRate": {
            "$convert": {
                "input": "$commonDeviceData.commonDeviceExtraData.respiratoryRate",
                "to": "int",
                "onError": 0,
                "onNull": 0
            }
        }
    }
}, {
    $group: {
        "_id": "$date",
        "heartRateAvg": {
            "$avg": "$heartRate"
        },
        "breathAvg": {
            "$avg": "$respiratoryRate"
        },
        "status": {
            "$last": "$status"
        },
        "date": {
            "$last": "$date"
        }
    }
}, {
    $project: {
        "date": {
            "$add": [ISODate("1970-01-01T00:00:00Z"), "$date"]
        },
        "heartRateAvg": 1,
        "breathAvg": 1,
        "status": 1
    }
}])
Aggregation agg = Aggregation.newAggregation(
        Aggregation.match(criteria),
        Aggregation.project()
                // 按半小时聚合,每半个小时聚合一条
                .andExpression("{$subtract:{{$subtract:{'$ts',new java.util.Date(0L)}},{$mod:{{$subtract: {'$ts',new java.util.Date(0L)}},1000 * 60 * 30}}}}").as("date")
                .and("commonDeviceData.commonDeviceExtraData.status").as("status")
                .and(ConvertOperators.Convert.convertValueOf("commonDeviceData.commonDeviceExtraData.heartRate")
                        .to("int")
                        .onErrorReturn(0)
                        .onNullReturn(0))
                .as("heartRate")
                .and(ConvertOperators.Convert.convertValueOf("commonDeviceData.commonDeviceExtraData.respiratoryRate")
                        .to("int")
                        .onErrorReturn(0)
                        .onNullReturn(0))
                .as("respiratoryRate"),
        Aggregation.group("date")
                .avg("heartRate").as("heartRateAvg")
                .avg("respiratoryRate").as("breathAvg")
                .last("status").as("status")
                .last("date").as("date"),
        Aggregation.project()
                .andExpression("{$add:{new java.util.Date(0L),'$date'}}").as("date")
                .and("heartRateAvg").as("heartRateAvg")
                .and("breathAvg").as("breathAvg")
                .and("status").as("status")
).withOptions(allowDiskOptions);
  1. 求平均
// 原生写法
db.deviceDataCollection_1452589816758669312.aggregate([
    {
        $match: {
            "deviceId": "84fd27fffe71b688",
            "huatuoDeviceData.sleepBandInfo.status": NumberInt("0"),
            "ts": {
                $gt: ISODate("2022-09-15T03:39:36Z"),
                $lt: ISODate("2022-09-15T03:39:36Z")
            }
        }
    },
    {
        $group: {
            _id: 
            '$deviceId',
            breathAvg: {
                $avg: "$huatuoDeviceData.sleepBandInfo.breathingRate"
            },
            heartRateAvg: {
                $avg: "$huatuoDeviceData.sleepBandInfo.heartRate"
            }
        }
    }
])
		// java template
		Criteria criteria = new Criteria();

        criteria.and("deviceId").is(deviceId);
        criteria.and("huatuoDeviceData.sleepBandInfo.status").is(0);
        Date startDate = string2Date(startTime, LocalDateTimeUtils.YYYY_MM_DD_HH_MM_SS);
        Date endDate = string2Date(endTime, LocalDateTimeUtils.YYYY_MM_DD_HH_MM_SS);
        if (startDate != null && endDate != null) {
            criteria.and("ts").gte(startDate).lte(endDate);
        }

        Aggregation agg = Aggregation.newAggregation(
                Aggregation.match(criteria),
                // 这里的group字段无所谓
                // avg as 的字段名要和实体对应上
                Aggregation.group("deviceId")
                    .avg("huatuoDeviceData.sleepBandInfo.breathingRate").as("breathAvg")
                    .avg("huatuoDeviceData.sleepBandInfo.heartRate").as("heartRateAvg")
        );

        AggregationResults<SleepDataEntity> aggregationResults =
                mongoTemplate.aggregate(agg, getCollectionName(tenantId), SleepDataEntity.class);
        if (!CollectionUtils.isEmpty(aggregationResults.getMappedResults())){
            return aggregationResults.getMappedResults().get(0);
        }
        return null;

4.字段为字符串 处理后求平均

db.deviceDataCollection_1475652926985990144.aggregate([
    {
        $match: {
            "_id": ObjectId("63229e80dea96d55a66a0d47")
        }
    },
    {
        $project: {
            groupId: {
                $convert: {
                    input: "$deviceId",
                    to: "string"
                }
            },
            heartRate: {
                $convert: {
                    input: "$commonDeviceData.commonDeviceExtraData.heartRate",
                    to: "int"
                }
            }
        }
    },
    {
        $group: {
            _id: 
            "$groupId",
            avghr: {
                $avg: "$heartRate"
            }
        }
    }
])
Aggregation agg = Aggregation.newAggregation(
                Aggregation.match(criteria),
                Aggregation.project()
                        .and("deviceId").as("groupId")
                        .and(ConvertOperators.Convert.convertValueOf("commonDeviceExtraData.respiratoryRate").to("int").onErrorReturn(0).onNullReturn(0)).as("breathRate")
                        .and(ConvertOperators.Convert.convertValueOf("commonDeviceExtraData.heartRate").to("int").onErrorReturn(0).onNullReturn(0)).as("heartRate"),
                Aggregation.group("groupId")
                        .avg("breathRate").as("avgbr")
                        .avg("heartRate").as("avghr")
        );

5.or

db.assets_feed.find({
    "tenantId": "1475652926985990144",
    "categoryId": {
        $in: ["62f34c86b9852679528db1e7"]
    },
    $or: [{
        "feedId": null
    }, {
        "feedId": {
            $exists: false
        }
    }]
})
public PageInfo<SimpleFeedEntity> getFeedsByCriteria(SimpleFeedEntity simpleFeedEntity, Integer pageNum, Integer pageSize) {
        Criteria criteria = new Criteria();
        criteria.and("tenantId").is(simpleFeedEntity.getTenantId());
        criteria.and("delFlag").is(false);
        if (StringUtils.isNotBlank(simpleFeedEntity.getId())) {
            criteria.and("_id").is(simpleFeedEntity.getId());
        }
        if (StringUtils.isNotBlank(simpleFeedEntity.getFeedId())) {
            criteria.and("feedId").is(simpleFeedEntity.getFeedId());
        }
        if (null != simpleFeedEntity.getFeedIdExist() && simpleFeedEntity.getFeedIdExist().equals(0) && StringUtils.isBlank(simpleFeedEntity.getFeedId())) {
            criteria.orOperator(Criteria.where("feedId").exists(false),Criteria.where("feedId").is(null));
        }
        if (StringUtils.isNotBlank(simpleFeedEntity.getStartStatus())) {
            criteria.and("startStatus").is(simpleFeedEntity.getStartStatus());
        }
        Query query = new Query(criteria);
        return findPage(pageNum, pageSize, query, SimpleFeedEntity.class);
    }

6.mongoDB update

db.getCollection("assets_feed").find({
    "delFlag": false,
    "durations.min": {
        "$exists": true
    }
}).forEach(function(item) {
    db.getCollection("assets_feed").update({
        _id: item._id
    }, {
        $set: {
            "durations": {
                "time": item.durations.min,
                "unit": "minute"
            }
        }
    });
})

7.mongoDB 批量更新

db.deviceDataCollection_1475652926985990144.update({
    "orgId": "1551852978372079616"
}, {
    $set: {
        "orgId": "1551852978372079617"
    }
}, {
    multi: true
})

8.mongoDB 批量更新时间

// 时间加一天
db.getCollection("deviceDataCollection_1475652926985990144").find({
    "deviceId": "SAD23423432"
}).forEach(function(item) {
    db.getCollection("deviceDataCollection_1475652926985990144").update({
        _id: item._id
    }, {
        $set: {
            ts: 
            new Date(item.ts.getTime() + 1000 * 3600 * 24)
        }
    });
})
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值