'use strict'; const Service = require('egg').Service; class DrivingBehaviorInfoService2 extends Service { // 基本方法 计算匹配的时间段下 过滤车型车系后时间分组下 维度分布分组数据之和 async index({ type, startTime, endTime, seriesCode, modelCode }, vString) { const { ctx } = this; const cond = [{ $match: {} }]; if (seriesCode) { cond[0].$match[`${vString}._id.series_code`] = seriesCode; } if (modelCode) { cond[0].$match[`${vString}._id.model_code`] = modelCode; } const agg = [ { $match: ctx.helper.getTimeRangMatch(startTime, endTime) }, { $unwind: `$${vString}` }, ...cond, ...ctx.helper.getCarTimeGroupMongo(type, vString), ]; return await ctx.model.Local.DrivingBehaviorInfoModel2.aggregateFix(agg); } // 计算车辆出行和疲劳驾驶次数 两个维度count和dsmCount(类似index) async mileageStartTimeAndDsm({ type, startTime, endTime, seriesCode, modelCode }) { const { ctx } = this; const cond = [{ $match: {} }]; if (seriesCode) { cond[0].$match['mileageStartTimeAndDsm._id.series_code'] = seriesCode; } if (modelCode) { cond[0].$match['mileageStartTimeAndDsm._id.model_code'] = modelCode; } const agg = [ { $match: ctx.helper.getTimeRangMatch(startTime, endTime) }, { $unwind: '$mileageStartTimeAndDsm' }, ...cond, ...ctx.helper.getCarDSMTimeGroupMongo(type), ]; return await ctx.model.Local.DrivingBehaviorInfoModel2.aggregateFix(agg); } // 带有周末时间过滤(类似index) async date({ type, startTime, endTime, seriesCode, modelCode, week = 0 }, vString) { const { ctx } = this; const cond = [{ $match: {} }]; const weekCond = [{ $match: {} }]; const project = { $project: { year: 1, month: 1, day: 1, week: { $dayOfWeek: { date: { $toDate: '$create_date' }, timezone: 'Asia/Shanghai' } } } }; project.$project[vString] = 1; if (seriesCode) { cond[0].$match[`${vString}._id.series_code`] = seriesCode; } if (modelCode) { cond[0].$match[`${vString}._id.model_code`] = modelCode; } switch (week) { case 1: weekCond[0].$match.week = { $in: [ 2, 3, 4, 5, 6 ] }; break; case 2: weekCond[0].$match.week = { $in: [ 1, 7 ] }; break; default: break; } const agg = [ { $match: ctx.helper.getTimeRangMatch(startTime, endTime) }, project, ...weekCond, { $unwind: `$${vString}` }, ...cond, ...ctx.helper.getCarTimeGroupMongo(type, vString), ]; return await ctx.model.Local.DrivingBehaviorInfoModel2.aggregateFix(agg); } // 求多个空调维度数据(无时间分组) async air({ startTime, endTime, seriesCode, modelCode }) { const { ctx } = this; const cond = [{ $match: {} }]; if (seriesCode) { cond[0].$match['airAvg._id.series_code'] = seriesCode; } if (modelCode) { cond[0].$match['airAvg._id.model_code'] = modelCode; } const agg = [ { $match: ctx.helper.getTimeRangMatch(startTime, endTime) }, { $unwind: '$data' }, ...cond, { $group: { _id: null, count: { $sum: '$data.count' }, airDuration: { $sum: '$data.airDuration' }, onCompressorDuration: { $sum: '$data.onCompressorDuration' }, offCompressorDuration: { $sum: '$data.offCompressorDuration' }, onAutoDuration: { $sum: '$data.onAutoDuration' }, offAutoDuration: { $sum: '$data.offAutoDuration' }, blowerRatingOneDuration: { $sum: '$data.blowerRatingOneDuration' }, blowerRatingTwoDuration: { $sum: '$data.blowerRatingTwoDuration' }, blowerRatingThreeDuration: { $sum: '$data.blowerRatingThreeDuration' }, blowerRatingFourDuration: { $sum: '$data.blowerRatingFourDuration' }, blowerRatingOtherDuration: { $sum: '$data.blowerRatingOtherDuration' } } }, { $project: { airDuration: { $cond: { if: { $eq: [ '$count', 0 ] }, then: 0, else: { $divide: [ '$airDuration', '$count' ] }, }, }, onCompressorDuration: { $cond: { if: { $eq: [ '$count', 0 ] }, then: 0, else: { $divide: [ '$onCompressorDuration', '$count' ] }, }, }, offCompressorDuration: { $cond: { if: { $eq: [ '$count', 0 ] }, then: 0, else: { $divide: [ '$offCompressorDuration', '$count' ] }, }, }, onAutoDuration: { $cond: { if: { $eq: [ '$count', 0 ] }, then: 0, else: { $divide: [ '$onAutoDuration', '$count' ] }, }, }, offAutoDuration: { $cond: { if: { $eq: [ '$count', 0 ] }, then: 0, else: { $divide: [ '$offAutoDuration', '$count' ] }, }, }, blowerRatingOneDuration: { $cond: { if: { $eq: [ '$count', 0 ] }, then: 0, else: { $divide: [ '$blowerRatingOneDuration', '$count' ] }, }, }, blowerRatingTwoDuration: { $cond: { if: { $eq: [ '$count', 0 ] }, then: 0, else: { $divide: [ '$blowerRatingTwoDuration', '$count' ] }, }, }, blowerRatingThreeDuration: { $cond: { if: { $eq: [ '$count', 0 ] }, then: 0, else: { $divide: [ '$blowerRatingThreeDuration', '$count' ] }, }, }, blowerRatingFourDuration: { $cond: { if: { $eq: [ '$count', 0 ] }, then: 0, else: { $divide: [ '$blowerRatingFourDuration', '$count' ] }, }, }, blowerRatingOtherDuration: { $cond: { if: { $eq: [ '$count', 0 ] }, then: 0, else: { $divide: [ '$blowerRatingOtherDuration', '$count' ] }, }, }, } }, ]; const result = await ctx.model.Local.DrivingBehaviorInfoModel2.aggregateNGroup(agg); return Object.assign({ airDuration: 0, onCompressorDuration: 0, offCompressorDuration: 0, onAutoDuration: 0, offAutoDuration: 0, blowerRatingOneDuration: 0, blowerRatingTwoDuration: 0, blowerRatingThreeDuration: 0, blowerRatingFourDuration: 0, blowerRatingOtherDuration: 0 }, result); } // 求位置维度数据(无时间分组)油耗平均 async avgOil({ startTime, endTime, seriesCode, modelCode, level }) { const { ctx } = this; const obj = `oil${level.charAt(0).toUpperCase()}${level.slice(1)}`; const cond = [{ $match: {} }]; if (seriesCode) { cond[0].$match[`${obj}._id.series_code`] = seriesCode; } if (modelCode) { cond[0].$match[`${obj}._id.model_code`] = modelCode; } const agg = [ { $match: ctx.helper.getTimeRangMatch(startTime, endTime) }, { $unwind: `$${obj}` }, ...cond, { $group: { _id: `$${obj}._id._id`, name: { $first: `$${obj}.name` }, count: { $avg: `$${obj}.avgOil` } } }, { $sort: { count: -1 } }, { $project: { name: 1, count: { $divide: [{ $trunc: { $multiply: [ '$count', 100 ] } }, 100 ] }, }, }, ]; return await ctx.model.Local.DrivingBehaviorInfoModel2.aggregateFix(agg); } // 求车辆某个维度数据之和(无时间分组) async sum({ startTime, endTime, seriesCode, modelCode }, vString) { const { ctx } = this; const cond = [{ $match: {} }]; if (seriesCode) { cond[0].$match[`${vString}._id.series_code`] = seriesCode; } if (modelCode) { cond[0].$match[`${vString}._id.model_code`] = modelCode; } const agg = [ { $match: ctx.helper.getTimeRangMatch(startTime, endTime) }, { $unwind: `$${vString}` }, ...cond, { $group: { _id: `$${vString}._id._id`, count: { $sum: `$${vString}.count` } } }, ]; return await ctx.model.Local.DrivingBehaviorInfoModel2.aggregateFix(agg); } // 基本方法 计算匹配的时间段下 过滤车型车系后时间分组下 维度分布分组数据平均值 async avg({ type, startTime, endTime, seriesCode, modelCode }, vString) { const { ctx } = this; const cond = [{ $match: {} }]; if (seriesCode) { cond[0].$match[`${vString}._id.series_code`] = seriesCode; } if (modelCode) { cond[0].$match[`${vString}._id.model_code`] = modelCode; } const agg = [ { $match: ctx.helper.getTimeRangMatch(startTime, endTime) }, { $unwind: `$${vString}` }, ...cond, ...ctx.helper.getCarAvgTimeGroupMongo(type, vString), ]; return await ctx.model.Local.DrivingBehaviorInfoModel2.aggregateFix(agg); } // 求平均值数据下某个维度 对应时间段的平均值 async count({ type, startTime, endTime, seriesCode, modelCode }, vString) { const { ctx } = this; const cond = [{ $match: {} }]; if (seriesCode) { cond[0].$match[`${vString}._id.series_code`] = seriesCode; } if (modelCode) { cond[0].$match[`${vString}._id.model_code`] = modelCode; } const agg = [ { $match: ctx.helper.getTimeRangMatch(startTime, endTime) }, { $unwind: '$data' }, ...cond, { $group: ctx.helper.getTimeGroup(type, { data: { $sum: `$data.${vString}` }, count: { $sum: '$data.count' }, }) }, { $project: { count: { $cond: { if: { $eq: [ '$count', 0 ] }, then: 0, else: { $divide: [{ $trunc: { $multiply: [{ $divide: [ '$data', '$count' ] }, 100 ] } }, 100 ] } } }, } }, ]; return await ctx.model.Local.DrivingBehaviorInfoModel2.aggregateFix(agg); } // 求平均值数据下某个不是平均值(是总和)维度的数据 对应时间段的总和 async count2({ type, startTime, endTime, seriesCode, modelCode }, vString) { const { ctx } = this; const cond = [{ $match: {} }]; if (seriesCode) { cond[0].$match[`${vString}._id.series_code`] = seriesCode; } if (modelCode) { cond[0].$match[`${vString}._id.model_code`] = modelCode; } const agg = [ { $match: ctx.helper.getTimeRangMatch(startTime, endTime) }, { $unwind: '$data' }, ...cond, { $group: ctx.helper.getTimeGroup(type, { count: { $sum: `$data.${vString}` } }) }, ]; return await ctx.model.Local.DrivingBehaviorInfoModel2.aggregateFix(agg); } // 统计清洗 async statistics({ timeRangData, initData, isForceUpdate }) { const { ctx } = this; const hasData = await ctx.service.statisticsService.saveBefore(ctx.model.Local.DrivingBehaviorInfoModel2, { ...initData }); if (hasData && !isForceUpdate) { return; } initData.start_time = new Date(); const dHour = { $add: [{ $multiply: [{ $hour: { $toDate: '$$this.start_time' } }, 60 ] }, { $minute: { $toDate: '$$this.start_time' } }] }; const mileageCnt = await this.bucketGroup(timeRangData, { $toDouble: '$mileage_cnt' }, [ 0, 30, 60, 90, 120, 10 * 10000 ]); const mileage = await this.bucketGroup(timeRangData, { $toDouble: '$mileage' }, [ 0, 50, 100, 300, 500, 1000, 1500, 20000, 10000 * 10000 ]); const mileageAvg = await this.bucketGroup(timeRangData, { $cond: { if: { $eq: [{ $ifNull: [ '$mileage_cnt', 0 ] }, 0 ] }, then: 0, else: { $divide: [{ $toDouble: '$mileage' }, { $toDouble: '$mileage_cnt' }] } } }, [ 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120 ]); const supplementaryCnt = await this.bucketGroup(timeRangData, { $toDouble: '$supplementary_cnt' }, [ 0, 1, 20, 30, 40, 50, 10 * 10000 ]); // const morningStart = 420; const morningStart = 0; // const morningEnd = 570; const morningEnd = 960; // const eveningStart = 17 * 60; const eveningStart = 960; // const eveningEnd = 19 * 60 + 30; const eveningEnd = 2000; const data = await this.avgGroup(timeRangData, { batterySoc: { $sum: { $toDouble: '$battery_soc' } }, engineSpeed: { $sum: { $toDouble: '$engine_speed' } }, insideTemperature: { $sum: { $toDouble: '$inside_temperature' } }, outsideTemperature: { $sum: { $toDouble: '$outside_temperature' } }, powerBatterySoc: { $sum: { $toDouble: '$power_battery_soc' } }, chargeDuration: { $sum: { $divide: [{ $toDouble: '$charge_duration' }, 60 * 60 * 1000 ] } }, chargeCnt: { $sum: { $toDouble: '$charge_cnt' } }, skyDuration: { $sum: { $divide: [{ $toDouble: '$sky_duration' }, 60 * 1000 ] } }, headlightCnt: { $sum: { $toDouble: '$headlight_cnt' } }, headlightDuration: { $sum: { $divide: [{ $toDouble: '$headlight_duration' }, 60 * 1000 ] } }, highBeamCnt: { $sum: { $toDouble: '$high_beam_cnt' } }, highBeamDuration: { $sum: { $divide: [{ $toDouble: '$high_beam_duration' }, 60 * 1000 ] } }, airDuration: { $sum: { $toDouble: '$air_duration' } }, onCompressorDuration: { $sum: { $toDouble: '$on_compressor_duration' } }, offCompressorDuration: { $sum: { $toDouble: '$off_compressor_duration' } }, onAutoDuration: { $sum: { $toDouble: '$on_auto_duration' } }, offAutoDuration: { $sum: { $toDouble: '$off_auto_duration' } }, blowerRatingOneDuration: { $sum: { $toDouble: '$blower_rating_duration.one' } }, blowerRatingTwoDuration: { $sum: { $toDouble: '$blower_rating_duration.two' } }, blowerRatingThreeDuration: { $sum: { $toDouble: '$blower_rating_duration.three' } }, blowerRatingFourDuration: { $sum: { $toDouble: '$blower_rating_duration.four' } }, blowerRatingOtherDuration: { $sum: { $add: [{ $toDouble: '$blower_rating_duration.five' }, { $toDouble: '$blower_rating_duration.six' }, { $toDouble: '$blower_rating_duration.seven' }] } }, dsmCnt: { $sum: { $toDouble: '$dsm_cnt' } }, atNightDriveCnt: { $sum: { $toDouble: '$at_night_drive_cnt' } }, atNightDriveDuration: { $sum: { $divide: [{ $toDouble: '$at_night_drive_duration' }, 60 * 60 * 1000 ] } }, atNightDriveMileage: { $sum: { $toDouble: '$at_night_drive_mileage' } }, morningPeakDuration: { $sum: '$morningPeakDuration' }, morningPeakMileage: { $sum: '$morningPeakMileage' }, eveningPeakDuration: { $sum: '$eveningPeakDuration' }, eveningPeakMileage: { $sum: '$eveningPeakMileage' }, }, [{ $addFields: { morningPeakDuration: { $ifNull: [ { $sum: { $map: { input: '$mileage_list', in: { $cond: { if: { $and: [{ $gte: [ dHour, morningStart ] }, { $lt: [ dHour, morningEnd ] }] }, then: { $divide: [{ $toDouble: '$$this.drive_duration' }, 60 * 60 * 1000 ] }, else: 0 } } } } }, 0 ] }, morningPeakMileage: { $ifNull: [ { $sum: { $map: { input: '$mileage_list', in: { $cond: { if: { $and: [{ $gte: [ dHour, morningStart ] }, { $lt: [ dHour, morningEnd ] }] }, then: { $toDouble: '$$this.mileage' }, else: 0 } } } } }, 0 ] }, eveningPeakDuration: { $ifNull: [ { $sum: { $map: { input: '$mileage_list', in: { $cond: { if: { $and: [{ $gte: [ dHour, eveningStart ] }, { $lt: [ dHour, eveningEnd ] }] }, then: { $divide: [{ $toDouble: '$$this.drive_duration' }, 60 * 60 * 1000 ] }, else: 0 } } } } }, 0 ] }, eveningPeakMileage: { $ifNull: [ { $sum: { $map: { input: '$mileage_list', in: { $cond: { if: { $and: [{ $gte: [ dHour, eveningStart ] }, { $lt: [ dHour, eveningEnd ] }] }, then: { $toDouble: '$$this.mileage' }, else: 0 } } } } }, 0 ] }, } }] ); const batterySoc = await this.bucketGroup(timeRangData, { $toDouble: '$battery_soc' }, [ 0, 60, 70, 80, 90, 100 ]); const engineSpeed = await this.bucketGroup(timeRangData, { $toDouble: '$engine_speed' }, [ 0, 2000, 3000, 4000, 5000, 10000 * 10000 ]); const insideTemperature = await this.bucketGroup(timeRangData, { $toDouble: '$inside_temperature' }, [ -1000, 30, 35, 40, 45, 50 ]); const outsideTemperature = await this.bucketGroup(timeRangData, { $toDouble: '$outside_temperature' }, [ -1000, 0, 10, 20, 30, 1000 ]); const powerBatterySoc = await this.bucketGroup(timeRangData, { $toDouble: '$power_battery_soc' }, [ 0, 60, 70, 80, 90, 100 ]); const chargeDuration = await this.bucketGroup(timeRangData, { $divide: [{ $toDouble: '$charge_duration' }, 60 * 60 * 1000 ] }, [ 0, 1, 2, 3, 4, 24 ]); const chargeStartSoc = await this.bucketGroup(timeRangData, '$chargeStartSoc', [ 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100 ], [{ $addFields: { chargeStartSoc: { $ifNull: [ { $avg: { $map: { input: '$charge_list', in: { $toDouble: '$$this.start_soc' } } } }, 0 ] } } }]); const chargeEndSoc = await this.bucketGroup(timeRangData, '$chargeEndSoc', [ 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100 ], [{ $addFields: { chargeEndSoc: { $ifNull: [ { $avg: { $map: { input: '$charge_list', in: { $toDouble: '$$this.end_soc' } } } }, 0 ] } } }]); const chargePreStartMileage = await this.bucketGroup(timeRangData, '$chargePreStartMileage', [ 0, 50, 100, 150, 200, 250, 300, 350, 400 ], [{ $addFields: { chargePreStartMileage: { $ifNull: [ { $avg: { $map: { input: '$charge_list', in: { $toDouble: '$$this.pre_start_mileage' } } } }, 0 ] } } }]); const chargeStartTime = await this.group(timeRangData, { $hour: { $toDate: '$charge_list.start_time' } }, [{ $unwind: '$charge_list' }] ); const chargeType = await this.group(timeRangData, { $toDouble: '$charge_list.charge_type' }, [{ $unwind: '$charge_list' }] ); const chargeMileage = await this.bucketGroup(timeRangData, '$chargeMileage', [ 0, 50, 100, 150, 200, 250, 300, 10000 * 10000 ], [{ $addFields: { chargeMileage: { $ifNull: [ { $avg: { $map: { input: '$charge_list', in: { $toDouble: '$$this.mileage' } } } }, 0 ] } } }]); const avgSpeedPower = await this.bucketGroup(timeRangData, { $toDouble: '$avg_speed' }, [ 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 1000 ], [], { $sum: { $toDouble: '$v.avg_power_consumption' } }, { avg_power_consumption: '$avg_power_consumption' }); const actualMileage = await this.bucketGroup(timeRangData, '$actualMileage', [ 0, 90, 100, 110, 120, 130, 140, 150, 160, 170, 180, 190, 10000 * 10000 ], [{ $addFields: { actualMileage: { $ifNull: [ { $avg: { $map: { input: '$actual_mileage_list', in: { $toDouble: '$$this.mileage' } } } }, 0 ] } } }]); const chargeCnt = await this.bucketGroup(timeRangData, { $toDouble: '$charge_cnt' }, [ 0, 50, 100, 150, 200, 10 * 10000 ]); const skyDuration = await this.bucketGroup(timeRangData, { $divide: [{ $toDouble: '$sky_duration' }, 60 * 1000 ] }, [ 0, 30, 60, 120, 180, 24 * 60 ]); const headlightCnt = await this.bucketGroup(timeRangData, { $toDouble: '$headlight_cnt' }, [ 0, 30, 60, 90, 120, 150, 180, 210, 240, 270, 300, 10 * 10000 ]); const headlightDuration = await this.bucketGroup(timeRangData, { $divide: [{ $toDouble: '$headlight_duration' }, 60 * 1000 ] }, [ 0, 0.5, 1, 3, 5, 8, 10, 15, 20, 25, 30, 40, 50, 24 * 60 ]); const highBeamCnt = await this.bucketGroup(timeRangData, { $toDouble: '$high_beam_cnt' }, [ 0, 30, 60, 90, 120, 150, 180, 210, 240, 270, 300, 10 * 10000 ]); const highBeamDuration = await this.bucketGroup(timeRangData, { $divide: [{ $toDouble: '$high_beam_duration' }, 60 * 1000 ] }, [ 0, 0.5, 1, 3, 5, 8, 10, 15, 20, 25, 30, 40, 50, 24 * 60 ]); const mileageStartTimeAndDsm = await this.group(timeRangData, { $hour: { $toDate: '$mileage_list.start_time' } }, [{ $unwind: '$mileage_list' }], { count: { $sum: 1 }, dsmCount: { $sum: { $cond: [{ $eq: [ '$mileage_list.dsm_status', 1 ] }, 1, 0 ] } } } ); const mileageCnt2 = await this.bucketGroup(timeRangData, { $toDouble: '$mileage_cnt' }, [ 0, 5, 10, 15, 20, 25, 30, 10 * 10000 ] ); const avgSpeed = await this.bucketGroup(timeRangData, { $toDouble: '$avg_speed' }, [ 0, 20, 30, 40, 50, 1000 ] ); const driveDuration = await this.bucketGroup(timeRangData, { $toDouble: '$drive_duration' }, [ 0, 1, 2, 3, 4, 24 ] ); const continuousDrive = await this.bucketGroup(timeRangData, { $divide: [{ $toDouble: '$mileage_list.drive_duration' }, 60 * 60 * 1000 ] }, [ 0, 1, 2, 3, 4, 24 ], [{ $unwind: '$mileage_list' }] ); const driveStyle = await this.group(timeRangData, '$mileage_list.drive_style', [{ $unwind: '$mileage_list' }], { count: { $sum: 1 } } ); const drivingSafetyScore = await this.bucketGroup(timeRangData, { $toDouble: '$driving_safety_score' }, [ 0, 60, 75, 90, 101 ] ); const energyConservationScore = await this.bucketGroup(timeRangData, { $toDouble: '$energy_conservation_score' }, [ 0, 60, 75, 90, 101 ] ); const mileageSingle = await this.bucketGroup(timeRangData, { $toDouble: '$mileage_list.mileage' }, [ 0, 10, 20, 30, 40, 50 ], [{ $unwind: '$mileage_list' }] ); const maxAcce = await this.bucketGroup(timeRangData, { $toDouble: '$mileage_list.max_acce' }, [ 0, 0.05, 0.1, 0.15, 0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5 ], [{ $unwind: '$mileage_list' }] ); const maxDece = await this.bucketGroup(timeRangData, { $toDouble: '$mileage_list.max_dece' }, [ 0, 0.05, 0.1, 0.15, 0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5, 0.55, 0.6, 0.65, 0.7, 0.75, 0.8 ], [{ $unwind: '$mileage_list' }] ); const sideAcce = await this.bucketGroup(timeRangData, { $toDouble: '$mileage_list.side_acce' }, [ 0, 0.05, 0.1, 0.15, 0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5 ], [{ $unwind: '$mileage_list' }] ); const oilProvince = await this.oilLocation(timeRangData, { _id: '$car.pro_code' }, [ { $lookup: { from: 't_sync_province', localField: '_id._id', foreignField: 'out_pro_code', as: 'pro' } }, { $unwind: '$pro' }, { $project: { avgOil: 1, name: '$pro.province_name' } }, ]); const oilCity = await this.oilLocation(timeRangData, { fid: '$car.pro_code', _id: '$car.city_code' }, [ { $lookup: { from: 't_sync_province', localField: '_id.fid', foreignField: 'out_pro_code', as: 'pro' } }, { $unwind: '$pro' }, { $lookup: { from: 't_sync_city', let: { city_code: '$_id._id', province_id: '$pro.province_id' }, pipeline: [{ $match: { $expr: { $and: [ { $eq: [ '$out_city_code', '$$city_code' ] }, { $eq: [ '$province_id', '$$province_id' ] }, ] } } }], as: 'city', } }, { $unwind: '$city' }, { $project: { avgOil: 1, name: '$city.city_name' } }, ]); await this.ctx.service.statisticsService.save(this.ctx.model.Local.DrivingBehaviorInfoModel2, { ...initData, mileageCnt, mileage, supplementaryCnt, batterySoc, engineSpeed, insideTemperature, outsideTemperature, powerBatterySoc, chargeDuration, chargeStartSoc, chargeEndSoc, chargePreStartMileage, chargeStartTime, chargeType, chargeMileage, avgSpeedPower, actualMileage, chargeCnt, skyDuration, headlightCnt, headlightDuration, highBeamCnt, highBeamDuration, mileageStartTimeAndDsm, driveDuration, mileageCnt2, avgSpeed, continuousDrive, driveStyle, mileageSingle, mileageAvg, drivingSafetyScore, energyConservationScore, maxAcce, maxDece, sideAcce, data, oilProvince, oilCity, }, isForceUpdate); } async oilLocation({ startTime, endTime }, group, lookups) { const { ctx } = this; const agg = [ { $match: ctx.helper.getTimeRangMatch(startTime, endTime, 'start_time') }, { $lookup: { from: 't_vehicle_record', localField: 'vin', foreignField: 'vin', as: 'car' } }, { $unwind: { path: '$car', preserveNullAndEmptyArrays: true } }, { $group: { _id: { series_code: '$car.series_code', model_code: '$car.model_code', ...group }, avgOil: { $avg: { $toDouble: '$avg_oil_consumption' } }, } }, ...lookups, ]; return await ctx.model.DrivingBehaviorInfoModel.aggregateFix(agg); } async bucketGroup({ startTime, endTime }, group, boundaries, otherCond = [], sum, bucketF) { const { ctx } = this; const agg = [ { $match: ctx.helper.getTimeRangMatch(startTime, endTime, 'start_time') }, ...otherCond, ...ctx.helper.getBucketMongo(group, boundaries, sum, bucketF), // 保证在这步骤前必须有条件字段和vin即可 ]; return await ctx.model.DrivingBehaviorInfoModel.aggregateFix(agg); } async group({ startTime, endTime }, group, otherCond, cond = { count: { $sum: 1 } }) { const { ctx } = this; const agg = [ { $match: ctx.helper.getTimeRangMatch(startTime, endTime, 'start_time') }, ...otherCond, { $lookup: { from: 't_vehicle_record', localField: 'vin', foreignField: 'vin', as: 'car' } }, { $unwind: { path: '$car', preserveNullAndEmptyArrays: true } }, { $group: { _id: { series_code: '$car.series_code', model_code: '$car.model_code', _id: group }, ...cond, } }, ]; return await ctx.model.DrivingBehaviorInfoModel.aggregateFix(agg); } async avgGroup({ startTime, endTime }, cond, otherCond) { const { ctx } = this; const agg = [ { $match: ctx.helper.getTimeRangMatch(startTime, endTime, 'start_time') }, ...otherCond, { $lookup: { from: 't_vehicle_record', localField: 'vin', foreignField: 'vin', as: 'car' } }, { $unwind: { path: '$car', preserveNullAndEmptyArrays: true } }, { $group: { _id: { series_code: '$car.series_code', model_code: '$car.model_code' }, ...cond, count: { $sum: 1 } } }, ]; return await ctx.model.DrivingBehaviorInfoModel.aggregateFix(agg); } } module.exports = DrivingBehaviorInfoService2;