|
@@ -141,63 +141,16 @@ class OnlineUserService2 extends Service {
|
|
|
return;
|
|
|
}
|
|
|
initData.start_time = new Date();
|
|
|
- let appTotal = 0;
|
|
|
- let appPlace = [];
|
|
|
- let tBoxTotal = 0;
|
|
|
- let tBoxPlace = [];
|
|
|
- let faceTotal = 0;
|
|
|
- let voiceTotal = 0;
|
|
|
- let pwdTotal = 0;
|
|
|
- let codeTotal = 0;
|
|
|
- let scanTotal = 0;
|
|
|
- ctx.logger.info("1");
|
|
|
- const iviTotal = await this.iviTotal(timeRangData);
|
|
|
- let carTotal = 0;
|
|
|
- let commonTotal = 0;
|
|
|
- let guestTotal = 0;
|
|
|
+
|
|
|
+ const { appTotal, iviTotal, tBoxTotal } = await this.count(timeRangData);
|
|
|
+ const total = appTotal + tBoxTotal;
|
|
|
+
|
|
|
+ const { faceTotal, voiceTotal, pwdTotal, codeTotal, scanTotal } = await this.modeGroup(timeRangData);
|
|
|
+
|
|
|
+ const { carTotal, commonTotal, guestTotal } = await this.roleGroup(timeRangData);
|
|
|
+
|
|
|
let successTotal = 0;
|
|
|
let failTotal = 0;
|
|
|
- ctx.logger.info("2");
|
|
|
- const modes = await this.modeGroup(timeRangData);
|
|
|
- modes.forEach(item => {
|
|
|
- switch (item._id) { // 1:人脸、2:声纹、3:密码、4:验证码、5:二维码
|
|
|
- case 'FACE':
|
|
|
- faceTotal += item.count;
|
|
|
- break;
|
|
|
- case 'SOUND':
|
|
|
- voiceTotal += item.count;
|
|
|
- break;
|
|
|
- case 'PASSWORD':
|
|
|
- pwdTotal += item.count;
|
|
|
- break;
|
|
|
- case 'VERIFICATION_CODE':
|
|
|
- codeTotal += item.count;
|
|
|
- break;
|
|
|
- case 'QR':
|
|
|
- scanTotal += item.count;
|
|
|
- break;
|
|
|
- default:
|
|
|
- break;
|
|
|
- }
|
|
|
- });
|
|
|
- ctx.logger.info("3");
|
|
|
- const roles = await this.roleGroup(timeRangData);
|
|
|
- roles.forEach(item => {
|
|
|
- switch (item._id) {
|
|
|
- case 'CAR_OWNER':
|
|
|
- carTotal += item.count;
|
|
|
- break;
|
|
|
- case 'user':
|
|
|
- commonTotal += item.count;
|
|
|
- break;
|
|
|
- case 'POTENTIAL':
|
|
|
- guestTotal += item.count;
|
|
|
- break;
|
|
|
- default:
|
|
|
- break;
|
|
|
- }
|
|
|
- });
|
|
|
- ctx.logger.info("4");
|
|
|
const status = await this.statusGroup(timeRangData);
|
|
|
status.forEach(item => {
|
|
|
switch (item._id) {
|
|
@@ -211,20 +164,18 @@ class OnlineUserService2 extends Service {
|
|
|
break;
|
|
|
}
|
|
|
});
|
|
|
- ctx.logger.info("5");
|
|
|
+
|
|
|
+ let appPlace = [];
|
|
|
+ let tBoxPlace = [];
|
|
|
const aResult = await this.appPlace(ctx.helper.getTimeRangMatch(
|
|
|
timeRangData.startTime, timeRangData.endTime, 'login_time'));
|
|
|
if (aResult && aResult.length > 0) {
|
|
|
- appTotal = aResult[0].count;
|
|
|
appPlace = aResult[0].areas;
|
|
|
}
|
|
|
- ctx.logger.info("6");
|
|
|
const tResult = await this.tBoxPlace(timeRangData);
|
|
|
if (tResult && tResult.length > 0) {
|
|
|
- tBoxTotal = tResult[0].count;
|
|
|
tBoxPlace = tResult[0].areas;
|
|
|
}
|
|
|
- const total = appTotal + tBoxTotal;
|
|
|
|
|
|
let appLocation = [];
|
|
|
let appNewLocation = [];
|
|
@@ -232,36 +183,30 @@ class OnlineUserService2 extends Service {
|
|
|
let iviLocation = [];
|
|
|
let iviNewLocation = [];
|
|
|
let iviActiveLocation = [];
|
|
|
- ctx.logger.info("7");
|
|
|
const al = await this.appPlace({ login_time: { $lt: timeRangData.endTime } });
|
|
|
if (al && al.length > 0) {
|
|
|
appLocation = al[0].areas;
|
|
|
}
|
|
|
- ctx.logger.info("8");
|
|
|
- // const anl = await this.appNewLocation(timeRangData);TODO 问题
|
|
|
- // if (anl && anl.length > 0) {
|
|
|
- // appNewLocation = anl[0].areas;
|
|
|
- // }
|
|
|
- ctx.logger.info("9");
|
|
|
- // const aal = await this.appActiveLocation(timeRangData);TODO 问题
|
|
|
- // if (aal && aal.length > 0) {
|
|
|
- // appActiveLocation = aal[0].areas;
|
|
|
- // }
|
|
|
- ctx.logger.info("10");
|
|
|
+ const anl = await this.appNewLocation(timeRangData);
|
|
|
+ if (anl && anl.length > 0) {
|
|
|
+ appNewLocation = anl[0].areas;
|
|
|
+ }
|
|
|
+ const aal = await this.appActiveLocation(timeRangData);
|
|
|
+ if (aal && aal.length > 0) {
|
|
|
+ appActiveLocation = aal[0].areas;
|
|
|
+ }
|
|
|
const il = await this.iviLocation(timeRangData);
|
|
|
if (il && il.length > 0) {
|
|
|
iviLocation = il[0].areas;
|
|
|
}
|
|
|
- ctx.logger.info("11");
|
|
|
- // const inl = await this.iviNewLocation(timeRangData);TODO 问题
|
|
|
- // if (inl && inl.length > 0) {
|
|
|
- // iviNewLocation = inl[0].areas;
|
|
|
- // }
|
|
|
- ctx.logger.info("12");
|
|
|
- // const ial = await this.iviActiveLocation(timeRangData);TODO 问题
|
|
|
- // if (ial && ial.length > 0) {
|
|
|
- // iviActiveLocation = ial[0].areas;
|
|
|
- // }
|
|
|
+ const inl = await this.iviNewLocation(timeRangData);
|
|
|
+ if (inl && inl.length > 0) {
|
|
|
+ iviNewLocation = inl[0].areas;
|
|
|
+ }
|
|
|
+ const ial = await this.iviActiveLocation(timeRangData);
|
|
|
+ if (ial && ial.length > 0) {
|
|
|
+ iviActiveLocation = ial[0].areas;
|
|
|
+ }
|
|
|
initData.end_time = new Date();
|
|
|
|
|
|
await ctx.service.statisticsService.save(ctx.model.Local.OnlineUserModel,
|
|
@@ -274,10 +219,20 @@ class OnlineUserService2 extends Service {
|
|
|
}, isForceUpdate);
|
|
|
}
|
|
|
|
|
|
- async iviTotal({ startTime, endTime }) {
|
|
|
+ async count({ startTime, endTime }) {
|
|
|
const { ctx } = this;
|
|
|
- return await ctx.model.IviOnlineUserModel.find(
|
|
|
+ let iviTotal = 0;
|
|
|
+ let appTotal = 0;
|
|
|
+ let tBoxTotal = 0;
|
|
|
+ iviTotal = await ctx.model.IviOnlineUserModel.find(
|
|
|
ctx.helper.getTimeRangMatch(startTime, endTime, 'login_time')).countDocuments();
|
|
|
+ appTotal = await ctx.model.AppOnlineUserModel.find(
|
|
|
+ { ...ctx.helper.getTimeRangMatch(startTime, endTime, 'login_time'), login_state: 1 })
|
|
|
+ .countDocuments();
|
|
|
+ tBoxTotal = await ctx.model.TBoxOnlineModel.find(
|
|
|
+ { ...ctx.helper.getTimeRangMatch(startTime, endTime, 'login_time'), login_state: 1 })
|
|
|
+ .countDocuments();
|
|
|
+ return { appTotal, tBoxTotal, iviTotal };
|
|
|
}
|
|
|
|
|
|
async modeGroup({ startTime, endTime }) {
|
|
@@ -286,9 +241,56 @@ class OnlineUserService2 extends Service {
|
|
|
{ $match: ctx.helper.getTimeRangMatch(startTime, endTime, 'login_time') },
|
|
|
{ $group: { _id: '$login_mode', count: { $sum: 1 } } },
|
|
|
];
|
|
|
+ let faceTotal = 0;
|
|
|
+ let voiceTotal = 0;
|
|
|
+ let pwdTotal = 0;
|
|
|
+ let codeTotal = 0;
|
|
|
+ let scanTotal = 0;
|
|
|
const aResult = await ctx.model.AppOnlineUserModel.aggregate(agg);
|
|
|
+ aResult.forEach(item => {
|
|
|
+ switch (item._id) { // 1:人脸、2:声纹、3:密码、4:验证码、5:二维码
|
|
|
+ case 'FACE':
|
|
|
+ faceTotal += item.count;
|
|
|
+ break;
|
|
|
+ case 'SOUND':
|
|
|
+ voiceTotal += item.count;
|
|
|
+ break;
|
|
|
+ case 'PASSWORD':
|
|
|
+ pwdTotal += item.count;
|
|
|
+ break;
|
|
|
+ case 'VERIFICATION_CODE':
|
|
|
+ codeTotal += item.count;
|
|
|
+ break;
|
|
|
+ case 'QR':
|
|
|
+ scanTotal += item.count;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ });
|
|
|
const iResult = await ctx.model.IviOnlineUserModel.aggregate(agg);
|
|
|
- return aResult.concat(iResult);
|
|
|
+ iResult.forEach(item => {
|
|
|
+ switch (item._id) { // 1:人脸、2:声纹、3:密码、4:验证码、5:二维码
|
|
|
+ case 1:
|
|
|
+ faceTotal += item.count;
|
|
|
+ break;
|
|
|
+ case 2:
|
|
|
+ voiceTotal += item.count;
|
|
|
+ break;
|
|
|
+ case 3:
|
|
|
+ pwdTotal += item.count;
|
|
|
+ break;
|
|
|
+ case 4:
|
|
|
+ codeTotal += item.count;
|
|
|
+ break;
|
|
|
+ case 5:
|
|
|
+ scanTotal += item.count;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ });
|
|
|
+ return { faceTotal, voiceTotal, pwdTotal, codeTotal, scanTotal };
|
|
|
}
|
|
|
|
|
|
async roleGroup({ startTime, endTime }) {
|
|
@@ -297,9 +299,42 @@ class OnlineUserService2 extends Service {
|
|
|
{ $match: ctx.helper.getTimeRangMatch(startTime, endTime, 'login_time') },
|
|
|
{ $group: { _id: '$role_id', count: { $sum: 1 } } },
|
|
|
];
|
|
|
+ let carTotal = 0;
|
|
|
+ let commonTotal = 0;
|
|
|
+ let guestTotal = 0;
|
|
|
const aResult = await ctx.model.AppOnlineUserModel.aggregate(agg);
|
|
|
+ aResult.forEach(item => {
|
|
|
+ switch (item._id) {
|
|
|
+ case 'CAR_OWNER':
|
|
|
+ carTotal += item.count;
|
|
|
+ break;
|
|
|
+ case 'user':
|
|
|
+ commonTotal += item.count;
|
|
|
+ break;
|
|
|
+ case 'POTENTIAL':
|
|
|
+ guestTotal += item.count;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ });
|
|
|
const iResult = await ctx.model.IviOnlineUserModel.aggregate(agg);
|
|
|
- return aResult.concat(iResult);
|
|
|
+ iResult.forEach(item => { // owner 是车主,common是使用人,guest是潜客(粉丝)
|
|
|
+ switch (item._id) {
|
|
|
+ case 'owner':
|
|
|
+ carTotal += item.count;
|
|
|
+ break;
|
|
|
+ case 'common':
|
|
|
+ commonTotal += item.count;
|
|
|
+ break;
|
|
|
+ case 'guest':
|
|
|
+ guestTotal += item.count;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ });
|
|
|
+ return { carTotal, commonTotal, guestTotal };
|
|
|
}
|
|
|
|
|
|
async statusGroup({ startTime, endTime }) {
|
|
@@ -313,212 +348,135 @@ class OnlineUserService2 extends Service {
|
|
|
return aResult.concat(iResult);
|
|
|
}
|
|
|
|
|
|
-
|
|
|
async appNewLocation(timeRangData) {
|
|
|
const { ctx } = this;
|
|
|
+ const userArr = await ctx.model.TRbacUserModel.find({
|
|
|
+ create_date: { $gte: ctx.helper.getMonthTop(timeRangData.startTime), $lt: timeRangData.endTime },
|
|
|
+ user_orgin: 'APP' }, { user_id: 1, _id: 0 });
|
|
|
+
|
|
|
const agg = [
|
|
|
- { $match: { login_state: 1 } },
|
|
|
- { $lookup: {
|
|
|
- from: 't_rbac_user',
|
|
|
- let: { user_id: '$user_Id' },
|
|
|
- pipeline: [{ $match: { $expr: { $and:
|
|
|
- [
|
|
|
- { $eq: [ '$user_id', '$$user_id' ] },
|
|
|
- { $gte: [ '$create_date', ctx.helper.getMonthTop(timeRangData.startTime) ] },
|
|
|
- { $lt: [ '$create_date', timeRangData.endTime ] },
|
|
|
- ] } } }], as: 'user',
|
|
|
- } },
|
|
|
- { $unwind: '$user' },
|
|
|
+ { $match: { login_time: { $gte: ctx.helper.getMonthTop(timeRangData.startTime), $lt: timeRangData.endTime },
|
|
|
+ login_state: 1, user_Id: { $in: userArr.map(item => item.user_id) } } },
|
|
|
{ $sort: { login_time: 1 } },
|
|
|
{ $group: { _id: '$user_Id',
|
|
|
- // area_code: { $first: '$area_code' }, area_name: { $first: '$area_name' },
|
|
|
- // provice_code: { $first: '$provice_code' }, city_code: { $first: '$city_code' },
|
|
|
provice_name: { $first: '$provice_name' }, city_name: { $first: '$city_name' } } },
|
|
|
- { $lookup: { from: 't_sync_province', localField: 'provice_name', foreignField: 'province_name', as: 'pro' } },
|
|
|
- { $unwind: '$pro' },
|
|
|
- { $lookup: {
|
|
|
- from: 't_sync_city',
|
|
|
- let: { city_name: '$city_name', province_id: '$pro.province_id' },
|
|
|
- pipeline: [{ $match: { $expr: { $and:
|
|
|
- [
|
|
|
- { $eq: [ '$city_name', '$$city_name' ] },
|
|
|
- { $eq: [ '$province_id', '$$province_id' ] },
|
|
|
- ] } } }], as: 'city',
|
|
|
- } },
|
|
|
- { $unwind: '$city' },
|
|
|
{ $lookup: { from: 't_sync_county', localField: 'provice_name', foreignField: 'province_name', as: 'area' } },
|
|
|
{ $project: {
|
|
|
- area_code: { $arrayElemAt: [ '$area.area_code', 0 ] },
|
|
|
area_name: { $arrayElemAt: [ '$area.area_name', 0 ] },
|
|
|
- provice_code: '$pro.pro_code',
|
|
|
- provice_name: '$pro.province_name',
|
|
|
- city_code: '$city.city_code',
|
|
|
- city_name: '$city.city_name',
|
|
|
+ provice_name: 1,
|
|
|
+ city_name: 1,
|
|
|
} },
|
|
|
+ { $match: { area_name: { $exists: true } } },
|
|
|
...ctx.helper.getLocationMongo(),
|
|
|
];
|
|
|
return await ctx.model.AppOnlineUserModel.aggregate(agg);
|
|
|
}
|
|
|
-
|
|
|
- async appActiveLocation({ startTime, endTime }) {
|
|
|
+ async iviNewLocation(timeRangData) {
|
|
|
const { ctx } = this;
|
|
|
- const agg = [
|
|
|
- ...ctx.helper.getAppActiveCond({ startTime, endTime }),
|
|
|
- ...ctx.helper.getLocationMongo(),
|
|
|
- ];
|
|
|
- return await ctx.model.AppOnlineUserModel.aggregate(agg);
|
|
|
- }
|
|
|
+ const userArr = await ctx.model.TRbacUserModel.find({
|
|
|
+ create_date: { $gte: ctx.helper.getMonthTop(timeRangData.startTime), $lt: timeRangData.endTime },
|
|
|
+ user_orgin: 'IVI' }, { user_id: 1, _id: 0 });
|
|
|
|
|
|
- async iviLocation({ endTime }) {
|
|
|
- const { ctx } = this;
|
|
|
const agg = [
|
|
|
- { $match: { login_time: { $lt: endTime }, login_state: 1 } },
|
|
|
+ { $match: { login_time: { $gte: ctx.helper.getMonthTop(timeRangData.startTime), $lt: timeRangData.endTime },
|
|
|
+ login_state: 1, user_id: { $in: userArr.map(item => item.user_id) } } },
|
|
|
{ $sort: { login_time: 1 } },
|
|
|
{ $group: { _id: '$user_id',
|
|
|
- county_code: { $first: '$county_code' }, county_name: { $first: '$county_name' },
|
|
|
provice_name: { $first: '$provice_name' }, city_name: { $first: '$city_name' } } },
|
|
|
- { $lookup: {
|
|
|
- from: 't_sync_county',
|
|
|
- let: { county_code: '$county_code', county_name: '$county_name', provice_name: '$provice_name', city_name: '$city_name' },
|
|
|
- pipeline: [{ $match: { $expr: { $and:
|
|
|
- [
|
|
|
- { $eq: [ '$out_county_code', '$$county_code' ] },
|
|
|
- { $eq: [ '$county_name', '$$county_name' ] },
|
|
|
- { $eq: [ '$province_name', '$$provice_name' ] },
|
|
|
- { $eq: [ '$city_name', '$$city_name' ] },
|
|
|
- ] } } }], as: 'location',
|
|
|
- } },
|
|
|
- { $unwind: '$location' },
|
|
|
+ { $lookup: { from: 't_sync_county', localField: 'provice_name', foreignField: 'province_name', as: 'area' } },
|
|
|
{ $project: {
|
|
|
- city_code: '$out_city_code',
|
|
|
- city_name: '$city_name',
|
|
|
- area_code: '$location.area_code',
|
|
|
- area_name: '$location.area_name',
|
|
|
- provice_code: '$out_pro_code',
|
|
|
- provice_name: '$provice_name',
|
|
|
+ area_name: { $arrayElemAt: [ '$area.area_name', 0 ] },
|
|
|
+ provice_name: 1,
|
|
|
+ city_name: 1,
|
|
|
} },
|
|
|
+ { $match: { area_name: { $exists: true } } },
|
|
|
...ctx.helper.getLocationMongo(),
|
|
|
];
|
|
|
return await ctx.model.IviOnlineUserModel.aggregate(agg);
|
|
|
}
|
|
|
-
|
|
|
- async iviNewLocation(timeRangData) {
|
|
|
+ async appActiveLocation({ startTime, endTime }) {
|
|
|
const { ctx } = this;
|
|
|
+ const appAgg = [
|
|
|
+ { $match: ctx.helper.getTimeRangMatch(startTime, endTime, 'create_time') },
|
|
|
+ { $group: { _id: '$user_id', use_duration: { $sum: '$use_duration' } } },
|
|
|
+ { $match: { use_duration: { $gt: 30 * 60 * 1000 } } },
|
|
|
+ ];
|
|
|
+ const result2 = await ctx.model.AppBehaviorRecordModel.aggregate(appAgg);
|
|
|
const agg = [
|
|
|
- { $match: { login_state: 1 } },
|
|
|
- { $lookup: {
|
|
|
- from: 't_rbac_user',
|
|
|
- let: { user_id: '$user_id' },
|
|
|
- pipeline: [{ $match: { $expr: { $and:
|
|
|
- [
|
|
|
- { $eq: [ '$user_id', '$$user_id' ] },
|
|
|
- { $gte: [ '$create_date', ctx.helper.getMonthTop(timeRangData.startTime) ] },
|
|
|
- { $lt: [ '$create_date', timeRangData.endTime ] },
|
|
|
- ] } } }], as: 'user',
|
|
|
- } },
|
|
|
- { $unwind: '$user' },
|
|
|
- { $sort: { login_time: 1 } },
|
|
|
- { $group: { _id: '$user_id',
|
|
|
- county_code: { $first: '$county_code' }, county_name: { $first: '$county_name' },
|
|
|
- provice_name: { $first: '$provice_name' }, city_name: { $first: '$city_name' } } },
|
|
|
- { $lookup: {
|
|
|
- from: 't_sync_county',
|
|
|
- let: { county_code: '$county_code', county_name: '$county_name', provice_name: '$provice_name', city_name: '$city_name' },
|
|
|
- pipeline: [{ $match: { $expr: { $and:
|
|
|
- [
|
|
|
- { $eq: [ '$out_county_code', '$$county_code' ] },
|
|
|
- { $eq: [ '$county_name', '$$county_name' ] },
|
|
|
- { $eq: [ '$province_name', '$$provice_name' ] },
|
|
|
- { $eq: [ '$city_name', '$$city_name' ] },
|
|
|
- ] } } }], as: 'location',
|
|
|
+ { $match: { ...ctx.helper.getTimeRangMatch(startTime, endTime, 'login_time'), login_state: 1 } },
|
|
|
+ { $group: {
|
|
|
+ _id: '$user_Id', provice_name: { $first: '$provice_name' }, city_name: { $first: '$city_name' },
|
|
|
+ login_count: { $sum: 1 },
|
|
|
} },
|
|
|
- { $unwind: '$location' },
|
|
|
+ { $match: { $or: [{ _id: { $in: result2.map(item => item._id) } }, { login_count: { $gte: 3 } }] } },
|
|
|
+ { $lookup: { from: 't_sync_county', localField: 'provice_name', foreignField: 'province_name', as: 'area' } },
|
|
|
{ $project: {
|
|
|
- city_code: '$out_city_code',
|
|
|
- city_name: '$city_name',
|
|
|
- area_code: '$location.area_code',
|
|
|
- area_name: '$location.area_name',
|
|
|
- provice_code: '$out_pro_code',
|
|
|
- provice_name: '$provice_name',
|
|
|
+ area_name: { $arrayElemAt: [ '$area.area_name', 0 ] },
|
|
|
+ provice_name: 1,
|
|
|
+ city_name: 1,
|
|
|
} },
|
|
|
+ { $match: { area_name: { $exists: true } } },
|
|
|
...ctx.helper.getLocationMongo(),
|
|
|
];
|
|
|
- return await ctx.model.IviOnlineUserModel.aggregate(agg);
|
|
|
- }
|
|
|
|
|
|
+ return await ctx.model.AppOnlineUserModel.aggregate(agg);
|
|
|
+ }
|
|
|
async iviActiveLocation({ startTime, endTime }) {
|
|
|
const { ctx } = this;
|
|
|
const agg = [
|
|
|
{ $match: { ...ctx.helper.getTimeRangMatch(startTime, endTime, 'login_time'), login_state: 1 } },
|
|
|
{ $sort: { login_time: 1 } },
|
|
|
+ { $group: { _id: '$user_id', provice_name: { $first: '$provice_name' }, city_name: { $first: '$city_name' } } },
|
|
|
+ { $lookup: { from: 't_sync_county', localField: 'provice_name', foreignField: 'province_name', as: 'area' } },
|
|
|
+ { $project: {
|
|
|
+ area_name: { $arrayElemAt: [ '$area.area_name', 0 ] },
|
|
|
+ provice_name: 1,
|
|
|
+ city_name: 1,
|
|
|
+ } },
|
|
|
+ ...ctx.helper.getLocationMongo(),
|
|
|
+ ];
|
|
|
+ return await ctx.model.IviOnlineUserModel.aggregate(agg);
|
|
|
+ }
|
|
|
+ async iviLocation({ endTime }) {
|
|
|
+ const { ctx } = this;
|
|
|
+ const agg = [
|
|
|
+ { $match: { login_time: { $lt: endTime }, login_state: 1 } },
|
|
|
+ { $sort: { login_time: 1 } },
|
|
|
{ $group: { _id: '$user_id',
|
|
|
- county_code: { $first: '$county_code' }, county_name: { $first: '$county_name' },
|
|
|
provice_name: { $first: '$provice_name' }, city_name: { $first: '$city_name' } } },
|
|
|
- { $lookup: {
|
|
|
- from: 't_sync_county',
|
|
|
- let: { county_code: '$county_code', county_name: '$county_name', provice_name: '$provice_name', city_name: '$city_name' },
|
|
|
- pipeline: [{ $match: { $expr: { $and:
|
|
|
- [
|
|
|
- { $eq: [ '$out_county_code', '$$county_code' ] },
|
|
|
- { $eq: [ '$county_name', '$$county_name' ] },
|
|
|
- { $eq: [ '$province_name', '$$provice_name' ] },
|
|
|
- { $eq: [ '$city_name', '$$city_name' ] },
|
|
|
- ] } } }], as: 'location',
|
|
|
- } },
|
|
|
- { $unwind: '$location' },
|
|
|
+ { $lookup: { from: 't_sync_county', localField: 'provice_name', foreignField: 'province_name', as: 'area' } },
|
|
|
{ $project: {
|
|
|
- city_code: '$out_city_code',
|
|
|
- city_name: '$city_name',
|
|
|
- area_code: '$location.area_code',
|
|
|
- area_name: '$location.area_name',
|
|
|
- provice_code: '$out_pro_code',
|
|
|
- provice_name: '$provice_name',
|
|
|
+ area_name: { $arrayElemAt: [ '$area.area_name', 0 ] },
|
|
|
+ provice_name: 1,
|
|
|
+ city_name: 1,
|
|
|
} },
|
|
|
+ { $match: { area_name: { $exists: true } } },
|
|
|
...ctx.helper.getLocationMongo(),
|
|
|
];
|
|
|
return await ctx.model.IviOnlineUserModel.aggregate(agg);
|
|
|
}
|
|
|
-
|
|
|
async appPlace(cond) {
|
|
|
const { ctx } = this;
|
|
|
const agg = [
|
|
|
{ $match: { ...cond, login_state: 1 } },
|
|
|
{ $sort: { login_time: 1 } },
|
|
|
{ $group: { _id: '$user_Id',
|
|
|
- /* area_code: { $first: '$area_code' }, area_name: { $first: '$area_name' },
|
|
|
- provice_code: { $first: '$provice_code' },city_code: { $first: '$city_code' },*/
|
|
|
provice_name: { $first: '$provice_name' }, city_name: { $first: '$city_name' } } },
|
|
|
- { $lookup: { from: 't_sync_province', localField: 'provice_name', foreignField: 'province_name', as: 'pro' } },
|
|
|
- { $unwind: '$pro' },
|
|
|
- { $lookup: {
|
|
|
- from: 't_sync_city',
|
|
|
- let: { city_name: '$city_name', province_id: '$pro.province_id' },
|
|
|
- pipeline: [{ $match: { $expr: { $and:
|
|
|
- [
|
|
|
- { $eq: [ '$city_name', '$$city_name' ] },
|
|
|
- { $eq: [ '$province_id', '$$province_id' ] },
|
|
|
- ] } } }], as: 'city',
|
|
|
- } },
|
|
|
- { $unwind: '$city' },
|
|
|
{ $lookup: { from: 't_sync_county', localField: 'provice_name', foreignField: 'province_name', as: 'area' } },
|
|
|
{ $project: {
|
|
|
- area_code: { $arrayElemAt: [ '$area.area_code', 0 ] },
|
|
|
area_name: { $arrayElemAt: [ '$area.area_name', 0 ] },
|
|
|
- provice_code: '$pro.pro_code',
|
|
|
- provice_name: '$pro.province_name',
|
|
|
- city_code: '$city.city_code',
|
|
|
- city_name: '$city.city_name',
|
|
|
+ provice_name: 1,
|
|
|
+ city_name: 1,
|
|
|
} },
|
|
|
+ { $match: { area_name: { $exists: true } } },
|
|
|
...ctx.helper.getLocationMongo(),
|
|
|
];
|
|
|
return await ctx.model.AppOnlineUserModel.aggregate(agg);
|
|
|
}
|
|
|
-
|
|
|
async tBoxPlace({ startTime, endTime }) {
|
|
|
const { ctx } = this;
|
|
|
const agg = [
|
|
|
{ $match: ctx.helper.getTimeRangMatch(startTime, endTime, 'online_time') },
|
|
|
- { $sort: { online_time: 1 } },
|
|
|
{ $group: { _id: '$vin' } },
|
|
|
{ $lookup: { from: 't_vehicle_record', localField: '_id', foreignField: 'vin', as: 'car' } },
|
|
|
{ $unwind: '$car' },
|
|
@@ -536,11 +494,8 @@ class OnlineUserService2 extends Service {
|
|
|
{ $unwind: '$city' },
|
|
|
{ $lookup: { from: 't_sync_county', localField: 'car.pro_code', foreignField: 'out_pro_code', as: 'area' } },
|
|
|
{ $project: {
|
|
|
- area_code: { $arrayElemAt: [ '$area.area_code', 0 ] },
|
|
|
area_name: { $arrayElemAt: [ '$area.area_name', 0 ] },
|
|
|
- provice_code: '$car.pro_code',
|
|
|
provice_name: '$pro.province_name',
|
|
|
- city_code: '$car.city_code',
|
|
|
city_name: '$city.city_name',
|
|
|
} },
|
|
|
...ctx.helper.getLocationMongo(),
|