drivingBehaviorInfoService2.js 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796
  1. 'use strict';
  2. const Service = require('egg').Service;
  3. class DrivingBehaviorInfoService2 extends Service {
  4. // 基本方法 计算匹配的时间段下 过滤车型车系后时间分组下 维度分布分组数据之和
  5. async index({ type, startTime, endTime, seriesCode, modelCode }, vString) {
  6. const { ctx } = this;
  7. const cond = [{ $match: {} }];
  8. if (seriesCode) {
  9. cond[0].$match[`${vString}._id.series_code`] = seriesCode;
  10. }
  11. if (modelCode) {
  12. cond[0].$match[`${vString}._id.model_code`] = modelCode;
  13. }
  14. const agg = [
  15. { $match: ctx.helper.getTimeRangMatch(startTime, endTime) },
  16. { $unwind: `$${vString}` },
  17. ...cond,
  18. ...ctx.helper.getCarTimeGroupMongo(type, vString),
  19. ];
  20. return await ctx.model.Local.DrivingBehaviorInfoModel2.aggregateFix(agg);
  21. }
  22. // 月累计占比算法
  23. async mixMY({ type, startTime, endTime, seriesCode, modelCode }, vString) {
  24. const { ctx } = this;
  25. const cond = [{ $match: {} }];
  26. if (seriesCode) {
  27. cond[0].$match['count._id.series_code'] = seriesCode;
  28. }
  29. if (modelCode) {
  30. cond[0].$match['count._id.model_code'] = modelCode;
  31. }
  32. // {
  33. // ...baseCond, _id: { year: '$year', month: '$month' },
  34. // }
  35. const agg = [
  36. ...ctx.helper.getCommonAggMax({ type, startTime, endTime, value: vString }),
  37. { $unwind: '$count' },
  38. ...cond,
  39. ...ctx.helper.getCarTimeGroupMongo2(type),
  40. ];
  41. return await ctx.model.Local.DrivingBehaviorInfoModel2.aggregateFix(agg);
  42. }
  43. // 计算车辆出行和疲劳驾驶次数 两个维度count和dsmCount(类似index)
  44. async mileageStartTimeAndDsm({ type, startTime, endTime, seriesCode, modelCode }) {
  45. const { ctx } = this;
  46. const cond = [{ $match: {} }];
  47. if (seriesCode) {
  48. cond[0].$match['mileageStartTimeAndDsm._id.series_code'] = seriesCode;
  49. }
  50. if (modelCode) {
  51. cond[0].$match['mileageStartTimeAndDsm._id.model_code'] = modelCode;
  52. }
  53. const agg = [
  54. { $match: ctx.helper.getTimeRangMatch(startTime, endTime) },
  55. { $unwind: '$mileageStartTimeAndDsm' },
  56. ...cond,
  57. ...ctx.helper.getCarDSMTimeGroupMongo(type),
  58. ];
  59. return await ctx.model.Local.DrivingBehaviorInfoModel2.aggregateFix(agg);
  60. }
  61. // 带有周末时间过滤(类似index)
  62. async date({ type, startTime, endTime, seriesCode, modelCode, week = 0 }, vString) {
  63. const { ctx } = this;
  64. const cond = [{ $match: {} }];
  65. const weekCond = [{ $match: {} }];
  66. const project = { $project: { year: 1, month: 1, day: 1,
  67. week: { $dayOfWeek: { date: { $toDate: '$create_date' }, timezone: 'Asia/Shanghai' } } } };
  68. project.$project[vString] = 1;
  69. if (seriesCode) {
  70. cond[0].$match[`${vString}._id.series_code`] = seriesCode;
  71. }
  72. if (modelCode) {
  73. cond[0].$match[`${vString}._id.model_code`] = modelCode;
  74. }
  75. switch (week) {
  76. case '1':
  77. weekCond[0].$match.week = { $in: [ 2, 3, 4, 5, 6 ] };
  78. break;
  79. case '2':
  80. weekCond[0].$match.week = { $in: [ 1, 7 ] };
  81. break;
  82. default:
  83. break;
  84. }
  85. const agg = [
  86. { $match: ctx.helper.getTimeRangMatch(startTime, endTime) },
  87. project,
  88. ...weekCond,
  89. { $unwind: `$${vString}` },
  90. ...cond,
  91. ...ctx.helper.getCarTimeGroupMongo(type, vString),
  92. ];
  93. return await ctx.model.Local.DrivingBehaviorInfoModel2.aggregateFix(agg);
  94. }
  95. // 求多个空调维度数据(无时间分组)
  96. async air({ startTime, endTime, seriesCode, modelCode }) {
  97. const { ctx } = this;
  98. const cond = [{ $match: {} }];
  99. if (seriesCode) {
  100. cond[0].$match['data._id.series_code'] = seriesCode;
  101. }
  102. if (modelCode) {
  103. cond[0].$match['data._id.model_code'] = modelCode;
  104. }
  105. const agg = [
  106. { $match: ctx.helper.getTimeRangMatch(startTime, endTime) },
  107. { $unwind: '$data' },
  108. ...cond,
  109. { $group: { _id: null, count: { $sum: '$data.count' },
  110. airDuration: { $sum: '$data.airDuration' },
  111. onCompressorDuration: { $sum: '$data.onCompressorDuration' },
  112. offCompressorDuration: { $sum: '$data.offCompressorDuration' },
  113. onAutoDuration: { $sum: '$data.onAutoDuration' },
  114. offAutoDuration: { $sum: '$data.offAutoDuration' },
  115. blowerRatingOneDuration: { $sum: '$data.blowerRatingOneDuration' },
  116. blowerRatingTwoDuration: { $sum: '$data.blowerRatingTwoDuration' },
  117. blowerRatingThreeDuration: { $sum: '$data.blowerRatingThreeDuration' },
  118. blowerRatingFourDuration: { $sum: '$data.blowerRatingFourDuration' },
  119. blowerRatingOtherDuration: { $sum: '$data.blowerRatingOtherDuration' } } },
  120. { $project: {
  121. airDuration: {
  122. $cond: {
  123. if: { $eq: [ '$count', 0 ] },
  124. then: 0, else: { $divide: [ '$airDuration', '$count' ] },
  125. },
  126. },
  127. onCompressorDuration: {
  128. $cond: {
  129. if: { $eq: [ '$count', 0 ] },
  130. then: 0, else: { $divide: [ '$onCompressorDuration', '$count' ] },
  131. },
  132. },
  133. offCompressorDuration: {
  134. $cond: {
  135. if: { $eq: [ '$count', 0 ] },
  136. then: 0, else: { $divide: [ '$offCompressorDuration', '$count' ] },
  137. },
  138. },
  139. onAutoDuration: {
  140. $cond: {
  141. if: { $eq: [ '$count', 0 ] },
  142. then: 0, else: { $divide: [ '$onAutoDuration', '$count' ] },
  143. },
  144. },
  145. offAutoDuration: {
  146. $cond: {
  147. if: { $eq: [ '$count', 0 ] },
  148. then: 0, else: { $divide: [ '$offAutoDuration', '$count' ] },
  149. },
  150. },
  151. blowerRatingOneDuration: {
  152. $cond: {
  153. if: { $eq: [ '$count', 0 ] },
  154. then: 0, else: { $divide: [ '$blowerRatingOneDuration', '$count' ] },
  155. },
  156. },
  157. blowerRatingTwoDuration: {
  158. $cond: {
  159. if: { $eq: [ '$count', 0 ] },
  160. then: 0, else: { $divide: [ '$blowerRatingTwoDuration', '$count' ] },
  161. },
  162. },
  163. blowerRatingThreeDuration: {
  164. $cond: {
  165. if: { $eq: [ '$count', 0 ] },
  166. then: 0, else: { $divide: [ '$blowerRatingThreeDuration', '$count' ] },
  167. },
  168. },
  169. blowerRatingFourDuration: {
  170. $cond: {
  171. if: { $eq: [ '$count', 0 ] },
  172. then: 0, else: { $divide: [ '$blowerRatingFourDuration', '$count' ] },
  173. },
  174. },
  175. blowerRatingOtherDuration: {
  176. $cond: {
  177. if: { $eq: [ '$count', 0 ] },
  178. then: 0, else: { $divide: [ '$blowerRatingOtherDuration', '$count' ] },
  179. },
  180. },
  181. } },
  182. ];
  183. const result = await ctx.model.Local.DrivingBehaviorInfoModel2.aggregateNGroup(agg);
  184. return Object.assign({ airDuration: 0, onCompressorDuration: 0, offCompressorDuration: 0,
  185. onAutoDuration: 0, offAutoDuration: 0,
  186. blowerRatingOneDuration: 0, blowerRatingTwoDuration: 0, blowerRatingThreeDuration: 0,
  187. blowerRatingFourDuration: 0, blowerRatingOtherDuration: 0 }, result);
  188. }
  189. // 求位置维度数据(无时间分组)油耗平均
  190. async avgOil({ startTime, endTime, seriesCode, modelCode, level }) {
  191. const { ctx } = this;
  192. const obj = `oil${level.charAt(0).toUpperCase()}${level.slice(1)}`;
  193. const cond = [{ $match: {} }];
  194. if (seriesCode) {
  195. cond[0].$match[`${obj}._id.series_code`] = seriesCode;
  196. }
  197. if (modelCode) {
  198. cond[0].$match[`${obj}._id.model_code`] = modelCode;
  199. }
  200. const agg = [
  201. { $match: ctx.helper.getTimeRangMatch(startTime, endTime) },
  202. { $unwind: `$${obj}` },
  203. ...cond,
  204. { $group: { _id: `$${obj}._id._id`, name: { $first: `$${obj}.name` },
  205. oil: { $sum: `$${obj}.oil` }, // 总油耗
  206. mileage: { $sum: `$${obj}.mileage` } } }, // 总公里
  207. { $sort: { count: -1 } },
  208. { $project:
  209. {
  210. name: 1,
  211. count: { $cond: [{ $eq: [ '$mileage', 0 ] }, 0, { $divide: [{ $trunc: { $multiply: [{ $divide: [ '$oil', '$mileage' ] }, 100 * 100 ] } }, 100 ] }] },
  212. },
  213. },
  214. ];
  215. return await ctx.model.Local.DrivingBehaviorInfoModel2.aggregateFix(agg);
  216. }
  217. // 求车辆某个维度数据之和(无时间分组)
  218. async sum({ startTime, endTime, seriesCode, modelCode }, vString) {
  219. const { ctx } = this;
  220. const cond = [{ $match: {} }];
  221. if (seriesCode) {
  222. cond[0].$match[`${vString}._id.series_code`] = seriesCode;
  223. }
  224. if (modelCode) {
  225. cond[0].$match[`${vString}._id.model_code`] = modelCode;
  226. }
  227. const agg = [
  228. { $match: ctx.helper.getTimeRangMatch(startTime, endTime) },
  229. { $unwind: `$${vString}` },
  230. ...cond,
  231. { $group: { _id: `$${vString}._id._id`, count: { $sum: `$${vString}.count` } } },
  232. ];
  233. return await ctx.model.Local.DrivingBehaviorInfoModel2.aggregateFix(agg);
  234. }
  235. // 基本方法 计算匹配的时间段下 过滤车型车系后时间分组下 维度分布分组数据平均值
  236. async avg({ type, startTime, endTime, seriesCode, modelCode }, vString) {
  237. const { ctx } = this;
  238. const cond = [{ $match: {} }];
  239. if (seriesCode) {
  240. cond[0].$match[`${vString}._id.series_code`] = seriesCode;
  241. }
  242. if (modelCode) {
  243. cond[0].$match[`${vString}._id.model_code`] = modelCode;
  244. }
  245. const agg = [
  246. { $match: ctx.helper.getTimeRangMatch(startTime, endTime) },
  247. { $unwind: `$${vString}` },
  248. ...cond,
  249. ...ctx.helper.getCarAvgTimeGroupMongo(type, vString),
  250. ];
  251. return await ctx.model.Local.DrivingBehaviorInfoModel2.aggregateFix(agg);
  252. }
  253. // 求平均值数据下某个维度 对应时间段的平均值
  254. async count({ type, startTime, endTime, seriesCode, modelCode }, vString) {
  255. const { ctx } = this;
  256. const cond = [{ $match: {} }];
  257. if (seriesCode) {
  258. cond[0].$match['data._id.series_code'] = seriesCode;
  259. }
  260. if (modelCode) {
  261. cond[0].$match['data._id.model_code'] = modelCode;
  262. }
  263. const agg = [
  264. { $match: ctx.helper.getTimeRangMatch(startTime, endTime) },
  265. { $unwind: '$data' },
  266. ...cond,
  267. { $group: ctx.helper.getTimeGroup(type, {
  268. data: { $sum: `$data.${vString}` }, count: { $sum: '$data.count' },
  269. }) },
  270. { $project: {
  271. count:
  272. { $cond: { if: { $eq: [ '$count', 0 ] },
  273. then: 0, else: { $divide: [{ $trunc: { $multiply: [{ $divide: [ '$data', '$count' ] }, 100 ] } }, 100 ] } } },
  274. } },
  275. ];
  276. return await ctx.model.Local.DrivingBehaviorInfoModel2.aggregateFix(agg);
  277. }
  278. // 求平均值数据下某个不是平均值(是总和)维度的数据 对应时间段的总和
  279. async count2({ type, startTime, endTime, seriesCode, modelCode }, vString) {
  280. const { ctx } = this;
  281. const cond = [{ $match: {} }];
  282. if (seriesCode) {
  283. cond[0].$match['data._id.series_code'] = seriesCode;
  284. }
  285. if (modelCode) {
  286. cond[0].$match['data._id.model_code'] = modelCode;
  287. }
  288. const agg = [
  289. { $match: ctx.helper.getTimeRangMatch(startTime, endTime) },
  290. { $unwind: '$data' },
  291. ...cond,
  292. { $group: ctx.helper.getTimeGroup(type, { count: { $sum: `$data.${vString}` } }) },
  293. { $project: {
  294. count: { $divide: [{ $trunc: { $multiply: [ '$count', 100 ] } }, 100 ] },
  295. } },
  296. ];
  297. return await ctx.model.Local.DrivingBehaviorInfoModel2.aggregateFix(agg);
  298. }
  299. // 统计清洗
  300. async statistics({ timeRangData, initData, isForceUpdate }) {
  301. const { ctx } = this;
  302. const hasData = await ctx.service.statisticsService.saveBefore(ctx.model.Local.DrivingBehaviorInfoModel2,
  303. { ...initData });
  304. if (hasData && !isForceUpdate) {
  305. return;
  306. }
  307. initData.start_time = new Date();
  308. const dHour = { $add: [{ $multiply: [
  309. { $hour: { date: { $toDate: '$$this.start_time' }, timezone: 'Asia/Shanghai' } },
  310. 60 ] },
  311. { $minute: { $toDate: '$$this.start_time' } }] };
  312. const mileage2 = await this.bucketGroup(timeRangData,
  313. { $toDouble: '$mileage' },
  314. [ 0, 5, 10, 20, 30, 50, 100, 200, 10000 * 10000 ]);
  315. ctx.logger.info('任务进行mileage2');
  316. const mileageAvg = await this.bucketGroup(timeRangData,
  317. { $toDouble: '$mileage_list.mileage' },
  318. [ 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 10 * 10000 ],
  319. [{ $unwind: '$mileage_list' }]
  320. );
  321. ctx.logger.info('任务进行mileageAvg');
  322. const supplementaryCnt = await this.bucketGroup(timeRangData,
  323. { $toDouble: '$supplementary_cnt' }, [ 0, 1, 20, 30, 40, 50, 10 * 10000 ]);
  324. ctx.logger.info('任务进行supplementaryCnt');
  325. const morningStart = 420;
  326. const morningEnd = 570;
  327. const eveningStart = 17 * 60;
  328. const eveningEnd = 19 * 60 + 30;
  329. const data = await this.avgGroup(timeRangData,
  330. {
  331. batterySoc: { $sum: { $toDouble: '$battery_soc' } },
  332. engineSpeed: { $sum: { $toDouble: '$engine_speed' } },
  333. insideTemperature: { $sum: { $toDouble: '$inside_temperature' } },
  334. outsideTemperature: { $sum: { $toDouble: '$outside_temperature' } },
  335. powerBatterySoc: { $sum: { $toDouble: '$power_battery_soc' } },
  336. chargeDuration: { $sum: { $divide: [{ $toDouble: '$charge_duration' }, 60 * 60 * 1000 ] } },
  337. chargeCnt: { $sum: { $toDouble: '$charge_cnt' } },
  338. skyDuration: { $sum: { $divide: [{ $toDouble: '$sky_duration' }, 60 * 1000 ] } },
  339. headlightCnt: { $sum: { $toDouble: '$headlight_cnt' } },
  340. headlightDuration: { $sum: { $divide: [{ $toDouble: '$headlight_duration' }, 60 * 1000 ] } },
  341. highBeamCnt: { $sum: { $toDouble: '$high_beam_cnt' } },
  342. highBeamDuration: { $sum: { $divide: [{ $toDouble: '$high_beam_duration' }, 60 * 1000 ] } },
  343. airDuration: { $sum: { $toDouble: '$air_duration' } },
  344. onCompressorDuration: { $sum: { $toDouble: '$on_compressor_duration' } },
  345. offCompressorDuration: { $sum: { $toDouble: '$off_compressor_duration' } },
  346. onAutoDuration: { $sum: { $toDouble: '$on_auto_duration' } },
  347. offAutoDuration: { $sum: { $toDouble: '$off_auto_duration' } },
  348. blowerRatingOneDuration: { $sum: { $toDouble: '$blower_rating_duration.one' } },
  349. blowerRatingTwoDuration: { $sum: { $toDouble: '$blower_rating_duration.two' } },
  350. blowerRatingThreeDuration: { $sum: { $toDouble: '$blower_rating_duration.three' } },
  351. blowerRatingFourDuration: { $sum: { $toDouble: '$blower_rating_duration.four' } },
  352. blowerRatingOtherDuration: { $sum: { $add: [{ $toDouble: '$blower_rating_duration.five' },
  353. { $toDouble: '$blower_rating_duration.six' }, { $toDouble: '$blower_rating_duration.seven' }] } },
  354. dsmCnt: { $sum: { $toDouble: '$dsm_cnt' } },
  355. atNightDriveCnt: { $sum: { $toDouble: '$at_night_drive_cnt' } },
  356. atNightDriveDuration: { $sum: { $divide: [{ $toDouble: '$at_night_drive_duration' }, 60 * 60 * 1000 ] } },
  357. atNightDriveMileage: { $sum: { $toDouble: '$at_night_drive_mileage' } },
  358. morningPeakDuration: { $sum: '$morningPeakDuration' },
  359. morningPeakMileage: { $sum: '$morningPeakMileage' },
  360. eveningPeakDuration: { $sum: '$eveningPeakDuration' },
  361. eveningPeakMileage: { $sum: '$eveningPeakMileage' },
  362. },
  363. [{ $addFields: {
  364. morningPeakDuration: { $ifNull: [
  365. { $sum: { $map: { input: '$mileage_list',
  366. in: { $cond: { if: { $and: [{ $gte: [ dHour, morningStart ] }, { $lt: [ dHour, morningEnd ] }] },
  367. then: { $divide: [{ $toDouble: '$$this.drive_duration' }, 60 * 60 * 1000 ] }, else: 0 } } } } }, 0 ] },
  368. morningPeakMileage: { $ifNull: [
  369. { $sum: { $map: { input: '$mileage_list',
  370. in: { $cond: { if: { $and: [{ $gte: [ dHour, morningStart ] }, { $lt: [ dHour, morningEnd ] }] },
  371. then: { $toDouble: '$$this.mileage' }, else: 0 } } } } }, 0 ] },
  372. eveningPeakDuration: { $ifNull: [
  373. { $sum: { $map: { input: '$mileage_list',
  374. in: { $cond: { if: { $and: [{ $gte: [ dHour, eveningStart ] }, { $lt: [ dHour, eveningEnd ] }] },
  375. then: { $divide: [{ $toDouble: '$$this.drive_duration' }, 60 * 60 * 1000 ] }, else: 0 } } } } }, 0 ] },
  376. eveningPeakMileage: { $ifNull: [
  377. { $sum: { $map: { input: '$mileage_list',
  378. in: { $cond: { if: { $and: [{ $gte: [ dHour, eveningStart ] }, { $lt: [ dHour, eveningEnd ] }] },
  379. then: { $toDouble: '$$this.mileage' }, else: 0 } } } } }, 0 ] },
  380. } }]
  381. );
  382. ctx.logger.info('任务进行avgGroup');
  383. const batterySoc = await this.bucketGroup(timeRangData,
  384. { $toDouble: '$battery_soc' }, [ 0, 60, 70, 80, 90, 101 ]);
  385. ctx.logger.info('任务进行batterySoc');
  386. const engineSpeed = await this.bucketGroup(timeRangData,
  387. { $toDouble: '$engine_speed' }, [ 0, 2000, 3000, 4000, 5000, 10000 * 10000 ]);
  388. ctx.logger.info('任务进行engineSpeed');
  389. const insideTemperature = await this.bucketGroup(timeRangData,
  390. { $toDouble: '$inside_temperature' }, [ -1000, 30, 35, 40, 45, 50 ]);
  391. ctx.logger.info('任务进行insideTemperature');
  392. const outsideTemperature = await this.bucketGroup(timeRangData,
  393. { $toDouble: '$outside_temperature' }, [ -1000, 0, 10, 20, 30, 1000 ]);
  394. ctx.logger.info('任务进行outsideTemperature');
  395. const powerBatterySoc = await this.bucketGroup(timeRangData,
  396. { $toDouble: '$power_battery_soc' }, [ 0, 60, 70, 80, 90, 101 ]);
  397. ctx.logger.info('任务进行powerBatterySoc');
  398. const chargeDuration = await this.bucketGroup(timeRangData,
  399. { $divide: [{ $toDouble: '$charge_duration' }, 60 * 60 * 1000 ] }, [ 0, 1, 2, 3, 4, 24 ]);
  400. ctx.logger.info('任务进行chargeDuration');
  401. const chargeStartSoc = await this.bucketGroup(timeRangData, '$chargeStartSoc', [ 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 101 ],
  402. [{ $addFields: { chargeStartSoc: { $ifNull: [
  403. { $avg: { $map: { input: '$charge_list', in: { $toDouble: '$$this.start_soc' } } } }, 0 ] } } }]);
  404. ctx.logger.info('任务进行chargeStartSoc');
  405. const chargeEndSoc = await this.bucketGroup(timeRangData, '$chargeEndSoc', [ 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 101 ],
  406. [{ $addFields: { chargeEndSoc: { $ifNull: [
  407. { $avg: { $map: { input: '$charge_list', in: { $toDouble: '$$this.end_soc' } } } }, 0 ] } } }]);
  408. ctx.logger.info('任务进行chargeEndSoc');
  409. const chargePreStartMileage = await this.bucketGroup(timeRangData, '$chargePreStartMileage',
  410. [ 0, 50, 100, 150, 200, 250, 300, 350, 400 ],
  411. [{ $addFields: { chargePreStartMileage: { $ifNull: [
  412. { $avg: { $map: { input: '$charge_list', in: { $toDouble: '$$this.pre_start_mileage' } } } }, 0 ] } } }]);
  413. ctx.logger.info('任务进行chargePreStartMileage');
  414. const chargeStartTime = await this.group(timeRangData,
  415. { $hour: { date: { $toDate: '$charge_list.start_time' }, timezone: 'Asia/Shanghai' } },
  416. [{ $unwind: '$charge_list' }]
  417. );
  418. ctx.logger.info('任务进行chargeStartTime');
  419. const chargeType = await this.group(timeRangData, { $toDouble: '$charge_list.charge_type' },
  420. [{ $unwind: '$charge_list' }]
  421. );
  422. ctx.logger.info('任务进行chargeType');
  423. const chargeMileage = await this.bucketGroup(timeRangData, '$chargeMileage',
  424. [ 0, 50, 100, 150, 200, 250, 300, 10000 * 10000 ],
  425. [{ $addFields: { chargeMileage: { $ifNull: [
  426. { $avg: { $map: { input: '$charge_list', in: { $toDouble: '$$this.mileage' } } } }, 0 ] } } }]);
  427. ctx.logger.info('任务进行chargeMileage');
  428. const avgSpeedPower = await this.bucketGroup(timeRangData,
  429. { $toDouble: '$avg_speed' }, [ 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 1000 ],
  430. [], { $sum: { $toDouble: '$v.avg_power_consumption' } },
  431. { avg_power_consumption: '$avg_power_consumption' });
  432. ctx.logger.info('任务进行avgSpeedPower');
  433. const actualMileage = await this.bucketGroup(timeRangData, '$actualMileage',
  434. [ 0, 100, 120, 140, 160, 180, 200, 220, 240, 260, 280, 300, 10000 * 10000 ],
  435. [{ $addFields: { actualMileage: { $ifNull: [
  436. { $avg: { $map: { input: '$actual_mileage_list', in: { $toDouble: '$$this.mileage' } } } }, 0 ] } } }]);
  437. ctx.logger.info('任务进行actualMileage');
  438. const mileageCnt = await this.bucketGroup(timeRangData,
  439. { $toDouble: '$mileage_cnt' }, [ 0, 30, 60, 90, 120, 10 * 10000 ]);
  440. ctx.logger.info('任务进行mileageCnt');
  441. const mileageCntMonth = await this.bucketDupGroupMonth(
  442. { startTime: ctx.helper.getMonthTop(timeRangData.startTime), endTime: timeRangData.endTime },
  443. { $toDouble: '$mileage_cnt' }, [ 0, 30, 60, 90, 120, 10 * 10000 ]);
  444. ctx.logger.info('任务进行mileageCntMonth');
  445. const mileageCntYear = await this.bucketDupGroupYear(
  446. { startTime: ctx.helper.nowYear(timeRangData.startTime), endTime: timeRangData.endTime },
  447. { $toDouble: '$mileage_cnt' }, [ 0, 300, 600, 900, 1200, 10 * 10000 ]);
  448. ctx.logger.info('任务进行mileageCntYear');
  449. // 0-500,500-1000,1000-1500,1500-2000,2000-3000,3000-4000,4000-5000,5000以上
  450. // 0-0.5万,0.5-1万,1万-1.5万,1.5-2万,2万-3万,3万-4万,4万-5万,5万以上
  451. const mileage = await this.bucketGroup(timeRangData,
  452. { $toDouble: '$mileage' }, [ 0, 50, 100, 300, 500, 1000, 1500, 20000, 10000 * 10000 ]);
  453. ctx.logger.info('任务进行mileage');
  454. const mileageMonth = await this.bucketDupGroupMonth(
  455. { startTime: ctx.helper.getMonthTop(timeRangData.startTime), endTime: timeRangData.endTime },
  456. { $toDouble: '$mileage' }, [ 0, 500, 1000, 1500, 2000, 3000, 4000, 5000, 10000 * 10000 ]);
  457. ctx.logger.info('任务进行mileageMonth');
  458. const mileageYear = await this.bucketDupGroupYear(
  459. { startTime: ctx.helper.nowYear(timeRangData.startTime), endTime: timeRangData.endTime },
  460. { $toDouble: '$mileage' }, [ 0, 5000, 10000, 15000, 20000, 30000, 40000, 50000, 10000 * 10000 ]);
  461. ctx.logger.info('任务进行mileageYear');
  462. const chargeCnt = await this.bucketGroup(timeRangData,
  463. { $toDouble: '$charge_cnt' }, [ 0, 50, 100, 150, 200, 10 * 10000 ]);
  464. ctx.logger.info('任务进行chargeCnt');
  465. const chargeCntMonth = await this.bucketDupGroupMonth(
  466. { startTime: ctx.helper.getMonthTop(timeRangData.startTime), endTime: timeRangData.endTime },
  467. { $toDouble: '$charge_cnt' }, [ 0, 5, 10, 15, 20, 10 * 10000 ]);
  468. ctx.logger.info('任务进行chargeCntMonth');
  469. const chargeCntYear = await this.bucketDupGroupYear(
  470. { startTime: ctx.helper.nowYear(timeRangData.startTime), endTime: timeRangData.endTime },
  471. { $toDouble: '$charge_cnt' }, [ 0, 50, 100, 150, 200, 10 * 10000 ]);
  472. ctx.logger.info('任务进行chargeCntYear');
  473. const skyDuration = await this.bucketGroup(timeRangData,
  474. { $divide: [{ $toDouble: '$sky_duration' }, 60 * 1000 ] },
  475. [ 0, 30, 60, 120, 180, 24 * 60 ]);
  476. ctx.logger.info('任务进行skyDuration');
  477. const skyDurationMonth = await this.bucketDupGroupMonth(
  478. { startTime: ctx.helper.getMonthTop(timeRangData.startTime), endTime: timeRangData.endTime },
  479. { $divide: [{ $toDouble: '$sky_duration' }, 60 * 60 * 1000 ] },
  480. [ 0, 0.5, 1, 2, 3, 24 * 60 ]);
  481. ctx.logger.info('任务进行skyDurationMonth');
  482. const skyDurationYear = await this.bucketDupGroupYear(
  483. { startTime: ctx.helper.nowYear(timeRangData.startTime), endTime: timeRangData.endTime },
  484. { $divide: [{ $toDouble: '$sky_duration' }, 60 * 60 * 1000 ] },
  485. [ 0, 5, 10, 20, 30, 24 * 60 ]);
  486. ctx.logger.info('任务进行skyDurationYear');
  487. const headlightCnt = await this.bucketGroup(timeRangData, { $toDouble: '$headlight_cnt' },
  488. [ 0, 30, 60, 90, 120, 150, 180, 210, 240, 270, 300, 10 * 10000 ]);
  489. ctx.logger.info('任务进行headlightCnt');
  490. const headlightCntMonth = await this.bucketDupGroupMonth(
  491. { startTime: ctx.helper.getMonthTop(timeRangData.startTime), endTime: timeRangData.endTime },
  492. { $toDouble: '$headlight_cnt' },
  493. [ 0, 30, 60, 90, 120, 150, 180, 210, 240, 270, 300, 10 * 10000 ]);
  494. ctx.logger.info('任务进行headlightCntMonth');
  495. const headlightCntYear = await this.bucketDupGroupYear(
  496. { startTime: ctx.helper.nowYear(timeRangData.startTime), endTime: timeRangData.endTime },
  497. { $toDouble: '$headlight_cnt' },
  498. [ 0, 300, 600, 900, 1200, 1500, 1800, 2100, 2400, 2700, 3000, 10 * 10000 ]);
  499. ctx.logger.info('任务进行headlightCntYear');
  500. const headlightDuration = await this.bucketGroup(timeRangData,
  501. { $divide: [{ $toDouble: '$headlight_duration' }, 60 * 1000 ] },
  502. [ 0, 0.5, 1, 3, 5, 8, 10, 15, 20, 25, 30, 40, 50, 24 * 60 ]);
  503. ctx.logger.info('任务进行headlightDuration');
  504. const headlightDurationMonth = await this.bucketDupGroupMonth(
  505. { startTime: ctx.helper.getMonthTop(timeRangData.startTime), endTime: timeRangData.endTime },
  506. { $divide: [{ $toDouble: '$headlight_duration' }, 60 * 60 * 1000 ] },
  507. [ 0, 0.5, 1, 1.5, 2, 2.5, 3, 3.5, 4, 4.5, 5, 5.5, 6, 24 * 60 ]);
  508. ctx.logger.info('任务进行headlightDurationMonth');
  509. const headlightDurationYear = await this.bucketDupGroupYear(
  510. { startTime: ctx.helper.nowYear(timeRangData.startTime), endTime: timeRangData.endTime },
  511. { $divide: [{ $toDouble: '$headlight_duration' }, 60 * 60 * 1000 ] },
  512. [ 0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 24 * 60 ]);
  513. ctx.logger.info('任务进行headlightDurationYear');
  514. const highBeamCnt = await this.bucketGroup(timeRangData, { $toDouble: '$high_beam_cnt' },
  515. [ 0, 30, 60, 90, 120, 150, 180, 210, 240, 270, 300, 10 * 10000 ]);
  516. ctx.logger.info('任务进行highBeamCnt');
  517. const highBeamCntMonth = await this.bucketDupGroupMonth(
  518. { startTime: ctx.helper.getMonthTop(timeRangData.startTime), endTime: timeRangData.endTime },
  519. { $toDouble: '$high_beam_cnt' },
  520. [ 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 10 * 10000 ]);
  521. ctx.logger.info('任务进行highBeamCntMonth');
  522. const highBeamCntYear = await this.bucketDupGroupYear(
  523. { startTime: ctx.helper.nowYear(timeRangData.startTime), endTime: timeRangData.endTime },
  524. { $toDouble: '$high_beam_cnt' },
  525. [ 0, 100, 200, 300, 400, 500, 600, 700, 800, 900, 1000, 10 * 10000 ]);
  526. ctx.logger.info('任务进行highBeamCntYear');
  527. const highBeamDuration = await this.bucketGroup(timeRangData,
  528. { $divide: [{ $toDouble: '$high_beam_duration' }, 60 * 1000 ] },
  529. [ 0, 0.5, 1, 3, 5, 8, 10, 15, 20, 25, 30, 40, 50, 24 * 60 ]);
  530. ctx.logger.info('任务进行highBeamDuration');
  531. const highBeamDurationMonth = await this.bucketDupGroupMonth(
  532. { startTime: ctx.helper.getMonthTop(timeRangData.startTime), endTime: timeRangData.endTime },
  533. { $divide: [{ $toDouble: '$high_beam_duration' }, 60 * 60 * 1000 ] },
  534. [ 0, 0.5, 1, 1.5, 2, 2.5, 3, 3.5, 4, 4.5, 5, 5.5, 6, 24 * 60 ]);
  535. ctx.logger.info('任务进行highBeamDurationMonth');
  536. const highBeamDurationYear = await this.bucketDupGroupYear(
  537. { startTime: ctx.helper.nowYear(timeRangData.startTime), endTime: timeRangData.endTime },
  538. { $divide: [{ $toDouble: '$high_beam_duration' }, 60 * 60 * 1000 ] },
  539. [ 0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 24 * 60 ]);
  540. ctx.logger.info('任务进行highBeamDurationYear');
  541. const mileageStartTimeAndDsm = await this.group(timeRangData, { $hour: { date: { $toDate: '$mileage_list.start_time' }, timezone: 'Asia/Shanghai' } },
  542. [{ $unwind: '$mileage_list' }],
  543. { count: { $sum: 1 }, dsmCount: { $sum: { $cond: [{ $eq: [ '$mileage_list.dsm_status', 1 ] }, 1, 0 ] } } }
  544. );
  545. ctx.logger.info('任务进行mileageStartTimeAndDsm');
  546. const mileageCnt2 = await this.bucketGroup(timeRangData, { $toDouble: '$mileage_cnt' },
  547. [ 1, 2, 3, 4, 5, 6, 7, 10 * 10000 ]
  548. );
  549. ctx.logger.info('任务进行mileageCnt2');
  550. const avgSpeed = await this.bucketGroup(timeRangData, { $toDouble: '$avg_speed' },
  551. [ 0, 20, 30, 40, 50, 1000 ]
  552. );
  553. ctx.logger.info('任务进行avgSpeed');
  554. const driveDuration = await this.bucketGroup(timeRangData,
  555. { $divide: [{ $toDouble: '$drive_duration' }, 60 * 60 * 1000 ] },
  556. [ 0, 1, 2, 3, 4, 24 ]
  557. );
  558. ctx.logger.info('任务进行driveDuration');
  559. const continuousDrive = await this.bucketGroup(timeRangData,
  560. { $divide: [{ $toDouble: '$mileage_list.drive_duration' }, 60 * 60 * 1000 ] },
  561. [ 0, 1, 2, 3, 4, 24 ],
  562. [{ $unwind: '$mileage_list' }]
  563. );
  564. ctx.logger.info('任务进行continuousDrive');
  565. const driveStyle = await this.group(timeRangData, '$mileage_list.drive_style',
  566. [{ $unwind: '$mileage_list' }],
  567. { count: { $sum: 1 } }
  568. );
  569. ctx.logger.info('任务进行driveStyle');
  570. const drivingSafetyScore = await this.bucketGroup(timeRangData, { $toDouble: '$driving_safety_score' },
  571. [ 0, 60, 75, 90, 101 ]
  572. );
  573. ctx.logger.info('任务进行drivingSafetyScore');
  574. const energyConservationScore = await this.bucketGroup(timeRangData, { $toDouble: '$energy_conservation_score' },
  575. [ 0, 60, 75, 90, 101 ]
  576. );
  577. ctx.logger.info('任务进行energyConservationScore');
  578. const mileageSingle = await this.bucketGroup(timeRangData,
  579. { $toDouble: '$mileage_list.mileage' },
  580. [ 0, 10, 20, 30, 40, 50 ],
  581. [{ $unwind: '$mileage_list' }]
  582. );
  583. ctx.logger.info('任务进行mileageSingle');
  584. const maxAcce = await this.bucketGroup(timeRangData, { $toDouble: '$mileage_list.max_acce' },
  585. [ 0, 0.05, 0.1, 0.15, 0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5 ],
  586. [{ $unwind: '$mileage_list' }]
  587. );
  588. ctx.logger.info('任务进行maxAcce');
  589. const maxDece = await this.bucketGroup(timeRangData, { $toDouble: '$mileage_list.max_dece' },
  590. [ 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 ],
  591. [{ $unwind: '$mileage_list' }]
  592. );
  593. ctx.logger.info('任务进行maxDece');
  594. const sideAcce = await this.bucketGroup(timeRangData, { $toDouble: '$mileage_list.side_acce' },
  595. [ 0, 0.05, 0.1, 0.15, 0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5 ],
  596. [{ $unwind: '$mileage_list' }]
  597. );
  598. ctx.logger.info('任务进行sideAcce');
  599. const oilProvince = await this.oilLocation(timeRangData, { _id: '$car.pro_code' },
  600. [
  601. { $lookup: { from: 't_sync_province', localField: '_id._id', foreignField: 'out_pro_code', as: 'pro' } },
  602. { $unwind: '$pro' },
  603. { $project: { oil: 1, mileage: 1, name: '$pro.province_name'/* ,avgOil:1*/ } },
  604. ]);
  605. ctx.logger.info('任务进行oilProvince');
  606. const oilCity = await this.oilLocation(timeRangData, { fid: '$car.pro_code', _id: '$car.city_code' },
  607. [
  608. { $lookup: { from: 't_sync_province', localField: '_id.fid', foreignField: 'out_pro_code', as: 'pro' } },
  609. { $unwind: '$pro' },
  610. { $lookup: {
  611. from: 't_sync_city',
  612. let: { city_code: '$_id._id', province_id: '$pro.province_id' },
  613. pipeline: [{ $match: { $expr: { $and:
  614. [
  615. { $eq: [ '$out_city_code', '$$city_code' ] },
  616. { $eq: [ '$province_id', '$$province_id' ] },
  617. ] } } }], as: 'city',
  618. } },
  619. { $unwind: '$city' },
  620. { $project: { oil: 1, mileage: 1, name: '$city.city_name'/* , avgOil:1 */ } },
  621. ]);
  622. ctx.logger.info('任务进行oilCity');
  623. await this.ctx.service.statisticsService.save(this.ctx.model.Local.DrivingBehaviorInfoModel2,
  624. { ...initData,
  625. mileage2, supplementaryCnt, batterySoc, engineSpeed, insideTemperature, outsideTemperature,
  626. powerBatterySoc, chargeDuration, chargeStartSoc, chargeEndSoc, chargePreStartMileage, chargeStartTime,
  627. chargeType, chargeMileage, avgSpeedPower, actualMileage,
  628. mileageCnt, mileageCntMonth, mileageCntYear, mileage, mileageMonth, mileageYear,
  629. chargeCnt, chargeCntMonth, chargeCntYear,
  630. skyDuration, skyDurationMonth, skyDurationYear,
  631. headlightCnt, headlightCntMonth, headlightCntYear,
  632. headlightDuration, headlightDurationMonth, headlightDurationYear,
  633. highBeamCnt, highBeamCntMonth, highBeamCntYear,
  634. highBeamDuration, highBeamDurationMonth, highBeamDurationYear,
  635. mileageStartTimeAndDsm, driveDuration, mileageCnt2, avgSpeed,
  636. continuousDrive, driveStyle, mileageSingle, mileageAvg,
  637. drivingSafetyScore, energyConservationScore,
  638. maxAcce, maxDece, sideAcce,
  639. data, oilProvince, oilCity,
  640. }, isForceUpdate);
  641. }
  642. async oilLocation({ startTime, endTime }, group, lookups) {
  643. const { ctx } = this;
  644. const agg = [
  645. { $match: ctx.helper.getTimeRangMatch(startTime, endTime, 'start_time') },
  646. { $lookup: { from: 't_vehicle_record', localField: 'vin', foreignField: 'vin', as: 'car' } },
  647. { $unwind: { path: '$car', preserveNullAndEmptyArrays: true } },
  648. { $addFields: { oil: { $multiply: [{ $divide: [{ $toDouble: '$avg_oil_consumption' }, 100 ] }, { $toDouble: '$mileage' }] } } },
  649. { $group: {
  650. _id: { series_code: '$car.series_code', model_code: '$car.model_code', ...group },
  651. oil: { $sum: '$oil' },
  652. mileage: { $sum: { $toDouble: '$mileage' } },
  653. // avgOil: { $avg: { $toDouble: '$avg_oil_consumption' } },
  654. } },
  655. ...lookups,
  656. ];
  657. return await ctx.model.DrivingBehaviorInfoModel.aggregateFix(agg);
  658. }
  659. async bucketGroup({ startTime, endTime }, group, boundaries, otherCond = [],
  660. sum = { $sum: 1 }, bucketF = {}) {
  661. const { ctx } = this;
  662. const agg = [
  663. { $match: ctx.helper.getTimeRangMatch(startTime, endTime, 'start_time') },
  664. ...otherCond,
  665. ...ctx.helper.getBucketMongo(group, boundaries, sum, bucketF), // 保证在这步骤前必须有条件字段和vin即可
  666. ];
  667. return await ctx.model.DrivingBehaviorInfoModel.aggregateFix(agg);
  668. }
  669. async bucketDupGroupMonth({ startTime, endTime }, group, boundaries) {
  670. const { ctx } = this;
  671. const agg = [
  672. { $match: ctx.helper.getTimeRangMatch(startTime, endTime, 'start_time') },
  673. { $group: {
  674. _id: { vin: '$vin',
  675. month: { $month: { date: { $toDate: '$start_time' }, timezone: 'Asia/Shanghai' } },
  676. year: { $year: { date: { $toDate: '$start_time' }, timezone: 'Asia/Shanghai' } },
  677. },
  678. count: { $sum: group },
  679. } },
  680. { $project: { vin: '$_id.vin', count: 1 } },
  681. ...ctx.helper.getBucketMongo('$count', boundaries), // 保证在这步骤前必须有条件字段和vin即可
  682. ];
  683. return await ctx.model.DrivingBehaviorInfoModel.aggregateFix(agg);
  684. }
  685. async bucketDupGroupYear({ startTime, endTime }, group, boundaries) {
  686. const { ctx } = this;
  687. const agg = [
  688. { $match: ctx.helper.getTimeRangMatch(startTime, endTime, 'start_time') },
  689. { $group: {
  690. _id: { vin: '$vin',
  691. year: { $year: { date: { $toDate: '$start_time' }, timezone: 'Asia/Shanghai' } },
  692. },
  693. count: { $sum: group },
  694. } },
  695. { $project: { vin: '$_id.vin', count: 1 } },
  696. ...ctx.helper.getBucketMongo('$count', boundaries), // 保证在这步骤前必须有条件字段和vin即可
  697. ];
  698. return await ctx.model.DrivingBehaviorInfoModel.aggregateFix(agg);
  699. }
  700. async group({ startTime, endTime }, group, otherCond, cond = { count: { $sum: 1 } }) {
  701. const { ctx } = this;
  702. const agg = [
  703. { $match: ctx.helper.getTimeRangMatch(startTime, endTime, 'start_time') },
  704. ...otherCond,
  705. { $lookup: { from: 't_vehicle_record', localField: 'vin', foreignField: 'vin', as: 'car' } },
  706. { $unwind: { path: '$car', preserveNullAndEmptyArrays: true } },
  707. { $group: {
  708. _id: { series_code: '$car.series_code', model_code: '$car.model_code', _id: group },
  709. ...cond,
  710. } },
  711. ];
  712. return await ctx.model.DrivingBehaviorInfoModel.aggregateFix(agg);
  713. }
  714. async avgGroup({ startTime, endTime }, cond, otherCond) {
  715. const { ctx } = this;
  716. const agg = [
  717. { $match: ctx.helper.getTimeRangMatch(startTime, endTime, 'start_time') },
  718. ...otherCond,
  719. { $lookup: { from: 't_vehicle_record', localField: 'vin', foreignField: 'vin', as: 'car' } },
  720. { $unwind: { path: '$car', preserveNullAndEmptyArrays: true } },
  721. { $group: { _id: { series_code: '$car.series_code', model_code: '$car.model_code' },
  722. ...cond, count: { $sum: 1 } } },
  723. ];
  724. return await ctx.model.DrivingBehaviorInfoModel.aggregateFix(agg);
  725. }
  726. }
  727. module.exports = DrivingBehaviorInfoService2;