Fixed perfs issue in lookups before sorting + bug in lookup and ID renaming in MongoDB
MODIFY
src/server/ocpp/utils/OCPPUtils.ts
src/server/ocpp/utils/OCPPUtils.ts
@@ -762,9 +762,9 @@ export default class OCPPUtils {
siteArea.maximumPower = consumption.limitSiteAreaWatts;
await SiteAreaStorage.saveSiteArea(tenantID, siteArea);
}
- }
consumption.smartChargingActive = siteArea.smartCharging;
}
+ }
public static async getChargingStationTemplate(chargingStation: ChargingStation): Promise<ChargingStationTemplate> {
let foundTemplate: ChargingStationTemplate = null;

MODIFY
src/server/rest/service/ChargingStationService.ts
src/server/rest/service/ChargingStationService.ts
@@ -82,7 +82,7 @@ export default class ChargingStationService {
// Check number of phases corresponds to the site area one
if (filteredRequest.connectors) {
for (const connector of filteredRequest.connectors) {
- if (connector.numberOfConnectedPhase !== 1 && chargingStation.siteArea.numberOfPhases === 1) {
+ if (connector.numberOfConnectedPhase !== 1 && chargingStation.siteArea && chargingStation.siteArea.numberOfPhases === 1) {
throw new AppError({
source: Constants.CENTRAL_SERVER,
action: action,

MODIFY
src/storage/mongodb/AssetStorage.ts
src/storage/mongodb/AssetStorage.ts
@@ -127,14 +127,6 @@ export default class AssetStorage {
$match: filters
});
}
- // Site Area
- if (params.withSiteArea) {
- DatabaseUtils.pushSiteAreaLookupInAggregation(
- {
- tenantID, aggregation, localField: 'siteAreaID', foreignField: '_id',
- asField: 'siteArea', oneToOneCardinality: true
- });
- }
// Limit records?
if (!dbParams.onlyRecordCount) {
// Always limit the nbr of record to avoid perfs issues
@@ -154,11 +146,6 @@ export default class AssetStorage {
}
// Remove the limit
aggregation.pop();
- // Handle the ID
- DatabaseUtils.pushRenameDatabaseID(aggregation);
- DatabaseUtils.pushConvertObjectIDToString(aggregation, 'siteAreaID');
- // Add Created By / Last Changed By
- DatabaseUtils.pushCreatedLastChangedInAggregation(tenantID, aggregation);
// Sort
if (dbParams.sort) {
aggregation.push({
@@ -177,6 +164,18 @@ export default class AssetStorage {
aggregation.push({
$limit: (limit > 0 && limit < Constants.DB_RECORD_COUNT_CEIL) ? limit : Constants.DB_RECORD_COUNT_CEIL
});
+ // Site Area
+ if (params.withSiteArea) {
+ DatabaseUtils.pushSiteAreaLookupInAggregation({
+ tenantID, aggregation, localField: 'siteAreaID', foreignField: '_id',
+ asField: 'siteArea', oneToOneCardinality: true
+ });
+ }
+ // Handle the ID
+ DatabaseUtils.pushRenameDatabaseID(aggregation);
+ DatabaseUtils.pushConvertObjectIDToString(aggregation, 'siteAreaID');
+ // Add Created By / Last Changed By
+ DatabaseUtils.pushCreatedLastChangedInAggregation(tenantID, aggregation);
// Project
DatabaseUtils.projectFields(aggregation, projectFields);
// Read DB

MODIFY
src/storage/mongodb/BillingStorage.ts
src/storage/mongodb/BillingStorage.ts
@@ -108,10 +108,6 @@ export default class BillingStorage {
}
// Remove the limit
aggregation.pop();
- // Add Last Changed / Created
- DatabaseUtils.pushCreatedLastChangedInAggregation(tenantID, aggregation);
- // Handle the ID
- DatabaseUtils.pushRenameDatabaseID(aggregation);
// Sort
if (dbParams.sort) {
aggregation.push({
@@ -130,6 +126,10 @@ export default class BillingStorage {
aggregation.push({
$limit: limit
});
+ // Add Last Changed / Created
+ DatabaseUtils.pushCreatedLastChangedInAggregation(tenantID, aggregation);
+ // Handle the ID
+ DatabaseUtils.pushRenameDatabaseID(aggregation);
// Project
DatabaseUtils.projectFields(aggregation, projectFields);
// Read DB

MODIFY
src/storage/mongodb/CarStorage.ts
src/storage/mongodb/CarStorage.ts
@@ -90,10 +90,6 @@ export default class CarStorage {
}
// Remove the limit
aggregation.pop();
- // Add Created By / Last Changed By
- DatabaseUtils.pushCreatedLastChangedInAggregation(Constants.DEFAULT_TENANT, aggregation);
- // Handle the ID
- DatabaseUtils.pushRenameDatabaseID(aggregation);
// Sort
if (dbParams.sort) {
aggregation.push({
@@ -112,6 +108,10 @@ export default class CarStorage {
aggregation.push({
$limit: (limit > 0 && limit < Constants.DB_RECORD_COUNT_CEIL) ? limit : Constants.DB_RECORD_COUNT_CEIL
});
+ // Add Created By / Last Changed By
+ DatabaseUtils.pushCreatedLastChangedInAggregation(Constants.DEFAULT_TENANT, aggregation);
+ // Handle the ID
+ DatabaseUtils.pushRenameDatabaseID(aggregation);
// Project
DatabaseUtils.projectFields(aggregation, projectFields);
// Read DB
@@ -591,6 +591,7 @@ export default class CarStorage {
}
// Create Aggregation
const aggregation = [];
+ // Filter on Users
if (!Utils.isEmptyArray(params.userIDs) || params.withUsers) {
DatabaseUtils.pushUserCarLookupInAggregation({
tenantID: tenantID, aggregation, localField: '_id', foreignField: 'carID',
@@ -609,26 +610,6 @@ export default class CarStorage {
$match: filters
});
}
- DatabaseUtils.pushCarCatalogLookupInAggregation({
- tenantID: Constants.DEFAULT_TENANT, aggregation, localField: 'carCatalogID', foreignField: '_id',
- asField: 'carCatalog', oneToOneCardinality: true
- });
- if (params.withUsers) {
- // Check
- const carUsersPipeline = [];
- if (!Utils.isEmptyArray(params.userIDs)) {
- carUsersPipeline.push({
- $match: {
- 'carUsers.userID': { $in: params.userIDs.map((userID) => Utils.convertToObjectID(userID)) }
- }
- });
- }
- // User on Car Users
- DatabaseUtils.pushArrayLookupInAggregation('carUsers', DatabaseUtils.pushUserLookupInAggregation.bind(this), {
- tenantID, aggregation: aggregation, localField: 'carUsers.userID', foreignField: '_id',
- asField: 'carUsers.user', oneToOneCardinality: true, objectIDFields: ['createdBy', 'lastChangedBy']
- }, carUsersPipeline);
- }
// Limit records?
if (!dbParams.onlyRecordCount) {
// Always limit the nbr of record to avoid perfs issues
@@ -648,10 +629,6 @@ export default class CarStorage {
}
// Remove the limit
aggregation.pop();
- // Add Created By / Last Changed By
- DatabaseUtils.pushCreatedLastChangedInAggregation(tenantID, aggregation);
- // Handle the ID
- DatabaseUtils.pushRenameDatabaseID(aggregation);
// Sort
if (dbParams.sort) {
aggregation.push({
@@ -675,6 +652,30 @@ export default class CarStorage {
aggregation.push({
$limit: (limit > 0 && limit < Constants.DB_RECORD_COUNT_CEIL) ? limit : Constants.DB_RECORD_COUNT_CEIL
});
+ // Add Created By / Last Changed By
+ DatabaseUtils.pushCreatedLastChangedInAggregation(tenantID, aggregation);
+ // Handle the ID
+ DatabaseUtils.pushRenameDatabaseID(aggregation);
+ // Add Users
+ if (params.withUsers) {
+ // Check
+ const carUsersPipeline = [];
+ if (!Utils.isEmptyArray(params.userIDs)) {
+ carUsersPipeline.push({
+ $match: { 'carUsers.userID': { $in: params.userIDs.map((userID) => Utils.convertToObjectID(userID)) } }
+ });
+ }
+ // User on Car Users
+ DatabaseUtils.pushArrayLookupInAggregation('carUsers', DatabaseUtils.pushUserLookupInAggregation.bind(this), {
+ tenantID, aggregation: aggregation, localField: 'carUsers.userID', foreignField: '_id',
+ asField: 'carUsers.user', oneToOneCardinality: true, objectIDFields: ['createdBy', 'lastChangedBy']
+ }, carUsersPipeline);
+ }
+ // Add Car Catalog
+ DatabaseUtils.pushCarCatalogLookupInAggregation({
+ tenantID: Constants.DEFAULT_TENANT, aggregation, localField: 'carCatalogID', foreignField: '_id',
+ asField: 'carCatalog', oneToOneCardinality: true
+ });
// Project
DatabaseUtils.projectFields(aggregation, projectFields);
// Read DB
@@ -812,10 +813,6 @@ export default class CarStorage {
$match: filters
});
}
- DatabaseUtils.pushUserLookupInAggregation({
- tenantID: tenantID, aggregation, localField: 'userID', foreignField: '_id',
- asField: 'user', oneToOneCardinality: true
- });
// Limit records?
if (!dbParams.onlyRecordCount) {
// Always limit the nbr of record to avoid perfs issues
@@ -835,12 +832,6 @@ export default class CarStorage {
}
// Remove the limit
aggregation.pop();
- // Convert Object ID to string
- DatabaseUtils.pushConvertObjectIDToString(aggregation, 'userID');
- // Add Created By / Last Changed By
- DatabaseUtils.pushCreatedLastChangedInAggregation(tenantID, aggregation);
- // Handle the ID
- DatabaseUtils.pushRenameDatabaseID(aggregation);
// Sort
if (dbParams.sort) {
aggregation.push({
@@ -859,6 +850,17 @@ export default class CarStorage {
aggregation.push({
$limit: limit
});
+ // Add User
+ DatabaseUtils.pushUserLookupInAggregation({
+ tenantID: tenantID, aggregation, localField: 'userID', foreignField: '_id',
+ asField: 'user', oneToOneCardinality: true
+ });
+ // Convert Object ID to string
+ DatabaseUtils.pushConvertObjectIDToString(aggregation, 'userID');
+ // Add Created By / Last Changed By
+ DatabaseUtils.pushCreatedLastChangedInAggregation(tenantID, aggregation);
+ // Handle the ID
+ DatabaseUtils.pushRenameDatabaseID(aggregation);
// Project
DatabaseUtils.projectFields(aggregation, projectFields);
// Read DB

MODIFY
src/storage/mongodb/ChargingStationStorage.ts
src/storage/mongodb/ChargingStationStorage.ts
@@ -208,13 +208,6 @@ export default class ChargingStationStorage {
tenantID, aggregation: aggregation, localField: 'siteAreaID', foreignField: '_id',
asField: 'siteArea', oneToOneCardinality: true, objectIDFields: ['createdBy', 'lastChangedBy']
});
- }
- // Date before provided
- if (params.statusChangedBefore && moment(params.statusChangedBefore).isValid()) {
- aggregation.push({
- $match: { 'connectors.statusLastChangedOn': { $lte: params.statusChangedBefore } }
- });
- }
// Check Site ID
if (params.siteIDs && Array.isArray(params.siteIDs)) {
// Build filter
@@ -226,15 +219,13 @@ export default class ChargingStationStorage {
}
});
}
- // Site
- if (params.withSite && !params.withNoSiteArea) {
- DatabaseUtils.pushSiteLookupInAggregation({
- tenantID, aggregation: aggregation, localField: 'siteArea.siteID', foreignField: '_id',
- asField: 'siteArea.site', oneToOneCardinality: true
+ }
+ // Date before provided
+ if (params.statusChangedBefore && moment(params.statusChangedBefore).isValid()) {
+ aggregation.push({
+ $match: { 'connectors.statusLastChangedOn': { $lte: params.statusChangedBefore } }
});
}
- // Convert siteID back to string after having queried the site
- DatabaseUtils.pushConvertObjectIDToString(aggregation, 'siteArea.siteID');
// Limit records?
if (!dbParams.onlyRecordCount) {
// Always limit the nbr of record to avoid perfs issues
@@ -254,15 +245,6 @@ export default class ChargingStationStorage {
}
// Remove the limit
aggregation.pop();
- // Users on connectors
- DatabaseUtils.pushArrayLookupInAggregation('connectors', DatabaseUtils.pushUserLookupInAggregation.bind(this), {
- tenantID, aggregation: aggregation, localField: 'connectors.userID', foreignField: '_id',
- asField: 'connectors.user', oneToOneCardinality: true, objectIDFields: ['createdBy', 'lastChangedBy']
- });
- // Add Created By / Last Changed By
- DatabaseUtils.pushCreatedLastChangedInAggregation(tenantID, aggregation);
- // Convert Object ID to string
- DatabaseUtils.pushConvertObjectIDToString(aggregation, 'siteAreaID');
// Sort
if (dbParams.sort) {
aggregation.push({
@@ -283,8 +265,26 @@ export default class ChargingStationStorage {
aggregation.push({
$limit: dbParams.limit
});
+ // Users on connectors
+ DatabaseUtils.pushArrayLookupInAggregation('connectors', DatabaseUtils.pushUserLookupInAggregation.bind(this), {
+ tenantID, aggregation: aggregation, localField: 'connectors.userID', foreignField: '_id',
+ asField: 'connectors.user', oneToOneCardinality: true, objectIDFields: ['createdBy', 'lastChangedBy']
+ });
+ // Site
+ if (params.withSite && !params.withNoSiteArea) {
+ DatabaseUtils.pushSiteLookupInAggregation({
+ tenantID, aggregation: aggregation, localField: 'siteArea.siteID', foreignField: '_id',
+ asField: 'siteArea.site', oneToOneCardinality: true
+ });
+ }
// Change ID
DatabaseUtils.pushRenameDatabaseID(aggregation);
+ // Convert siteID back to string after having queried the site
+ DatabaseUtils.pushConvertObjectIDToString(aggregation, 'siteArea.siteID');
+ // Add Created By / Last Changed By
+ DatabaseUtils.pushCreatedLastChangedInAggregation(tenantID, aggregation);
+ // Convert Object ID to string
+ DatabaseUtils.pushConvertObjectIDToString(aggregation, 'siteAreaID');
// Project
DatabaseUtils.projectFields(aggregation, projectFields);
// Read DB

MODIFY
src/storage/mongodb/DatabaseUtils.ts
src/storage/mongodb/DatabaseUtils.ts
@@ -137,7 +137,22 @@ export default class DatabaseUtils {
}`)
);
// Replace array
- lookupParams.aggregation.push(JSON.parse(`{ "$addFields": { "root.${arrayName}": { "$cond": { "if": { "$eq": [ "$${arrayName}", [{}] ] }, "then": [], "else": "$${arrayName}" } } } }`));
+ lookupParams.aggregation.push(JSON.parse(`{
+ "$addFields": {
+ "root.${arrayName}": {
+ "$cond": {
+ "if": {
+ "$or": [
+ { "$eq": [ "$${arrayName}", [{}] ] },
+ { "$eq": [ "$${arrayName}", [null] ] }
+ ]
+ },
+ "then": [],
+ "else": "$${arrayName}"
+ }
+ }
+ }
+ }`));
// Replace root
lookupParams.aggregation.push({ $replaceRoot: { newRoot: '$root' } });
}
@@ -194,6 +209,19 @@ export default class DatabaseUtils {
}
});
}
+ // Check if the target field is a composed property: empty root document must be null ({} = null)
+ const splitAsField = lookupParams.asField.split('.');
+ if (splitAsField.length > 1) {
+ lookupParams.aggregation.push(JSON.parse(`{
+ "$addFields": {
+ "${splitAsField[0]}": {
+ "$cond": {
+ "if": { "$eq": [ "$${splitAsField[0]}", ${lookupParams.oneToOneCardinality ? '{}' : '[]'} ] },
+ "then": null, "else": "$${splitAsField[0]}" }
+ }
+ }
+ }`));
+ }
}
public static pushChargingStationInactiveFlag(aggregation: any[]) {
@@ -233,6 +261,19 @@ export default class DatabaseUtils {
}
}
}`));
+ // Check if the field is a composed property: empty root document must be null ({} = null)
+ const splitFieldName = renamedFieldName.split('.');
+ if (splitFieldName.length === 2) {
+ aggregation.push(JSON.parse(`{
+ "$addFields": {
+ "${splitFieldName[0]}": {
+ "$cond": {
+ "if": { "$eq": [ "$${splitFieldName[0]}", { "${splitFieldName[1]}": null } ] },
+ "then": null, "else": "$${splitFieldName[0]}" }
+ }
+ }
+ }`));
+ }
}
public static clearFieldValueIfSubFieldIsNull(aggregation: any[], fieldName: string, subFieldName: string) {

MODIFY
src/storage/mongodb/SiteAreaStorage.ts
src/storage/mongodb/SiteAreaStorage.ts
@@ -186,13 +186,6 @@ export default class SiteAreaStorage {
$match: filters
});
}
- // Sites
- if (params.withSite) {
- DatabaseUtils.pushSiteLookupInAggregation({
- tenantID, aggregation, localField: 'siteID', foreignField: '_id',
- asField: 'site', oneToOneCardinality: true
- });
- }
// Limit records?
if (!dbParams.onlyRecordCount) {
// Always limit the nbr of record to avoid perfs issues
@@ -212,27 +205,12 @@ export default class SiteAreaStorage {
}
// Remove the limit
aggregation.pop();
- // Charging Stations
- if (params.withChargingStations || params.withAvailableChargers) {
- DatabaseUtils.pushChargingStationLookupInAggregation({
- tenantID, aggregation, localField: '_id', foreignField: 'siteAreaID',
- asField: 'chargingStations'
- });
- }
- // Convert Object ID to string
- DatabaseUtils.pushConvertObjectIDToString(aggregation, 'siteID');
- // Add Last Changed / Created
- DatabaseUtils.pushCreatedLastChangedInAggregation(tenantID, aggregation);
- // Handle the ID
- DatabaseUtils.pushRenameDatabaseID(aggregation);
- // Sort
+ // Add Sort
if (dbParams.sort) {
- // Sort
aggregation.push({
$sort: dbParams.sort
});
} else {
- // Default
aggregation.push({
$sort: { name: 1 }
});
@@ -245,6 +223,26 @@ export default class SiteAreaStorage {
aggregation.push({
$limit: limit
});
+ // Sites
+ if (params.withSite) {
+ DatabaseUtils.pushSiteLookupInAggregation({
+ tenantID, aggregation, localField: 'siteID', foreignField: '_id',
+ asField: 'site', oneToOneCardinality: true
+ });
+ }
+ // Charging Stations
+ if (params.withChargingStations || params.withAvailableChargers) {
+ DatabaseUtils.pushChargingStationLookupInAggregation({
+ tenantID, aggregation, localField: '_id', foreignField: 'siteAreaID',
+ asField: 'chargingStations'
+ });
+ }
+ // Convert Object ID to string
+ DatabaseUtils.pushConvertObjectIDToString(aggregation, 'siteID');
+ // Add Last Changed / Created
+ DatabaseUtils.pushCreatedLastChangedInAggregation(tenantID, aggregation);
+ // Handle the ID
+ DatabaseUtils.pushRenameDatabaseID(aggregation);
// Project
if (projectFields) {
DatabaseUtils.projectFields(aggregation,

MODIFY
src/storage/mongodb/SiteStorage.ts
src/storage/mongodb/SiteStorage.ts
@@ -119,7 +119,7 @@ export default class SiteStorage {
}
});
}
- // Get users
+ // Users
DatabaseUtils.pushUserLookupInAggregation({
tenantID, aggregation, localField: 'userID', foreignField: '_id',
asField: 'user', oneToOneCardinality: true, oneToOneCardinalityNotNull: true
@@ -142,9 +142,6 @@ export default class SiteStorage {
}
});
}
- // Convert IDs to String
- DatabaseUtils.pushConvertObjectIDToString(aggregation, 'userID');
- DatabaseUtils.pushConvertObjectIDToString(aggregation, 'siteID');
// Limit records?
if (!dbParams.onlyRecordCount) {
// Always limit the nbr of record to avoid perfs issues
@@ -181,6 +178,11 @@ export default class SiteStorage {
aggregation.push({
$limit: limit
});
+ // Handle the ID
+ DatabaseUtils.pushRenameDatabaseID(aggregation);
+ // Convert IDs to String
+ DatabaseUtils.pushConvertObjectIDToString(aggregation, 'userID');
+ DatabaseUtils.pushConvertObjectIDToString(aggregation, 'siteID');
// Project
DatabaseUtils.projectFields(aggregation, projectFields);
// Read DB
@@ -190,24 +192,13 @@ export default class SiteStorage {
allowDiskUse: true
})
.toArray();
- const users: UserSite[] = [];
- // Convert to typed object
- for (const siteUserMDB of siteUsersMDB) {
- if (siteUserMDB.user) {
- users.push({
- user: siteUserMDB.user, siteID: params.siteID,
- siteAdmin: !siteUserMDB.siteAdmin ? false : siteUserMDB.siteAdmin,
- siteOwner: !siteUserMDB.siteOwner ? false : siteUserMDB.siteOwner
- });
- }
- }
// Debug
Logging.traceEnd(MODULE_NAME, 'getSitesUsers', uniqueTimerID, { siteID: params.siteID });
// Ok
return {
count: (usersCountMDB.length > 0 ?
(usersCountMDB[0].count === Constants.DB_RECORD_COUNT_CEIL ? -1 : usersCountMDB[0].count) : 0),
- result: users
+ result: siteUsersMDB
};
}
@@ -383,20 +374,6 @@ export default class SiteStorage {
}
// Remove the limit
aggregation.pop();
- // Add Company
- if (params.withCompany) {
- DatabaseUtils.pushCompanyLookupInAggregation(
- {
- tenantID, aggregation, localField: 'companyID', foreignField: '_id',
- asField: 'company', oneToOneCardinality: true
- });
- }
- // Convert Object ID to string
- DatabaseUtils.pushConvertObjectIDToString(aggregation, 'companyID');
- // Add Last Changed / Created
- DatabaseUtils.pushCreatedLastChangedInAggregation(tenantID, aggregation);
- // Handle the ID
- DatabaseUtils.pushRenameDatabaseID(aggregation);
// Sort
if (dbParams.sort) {
aggregation.push({
@@ -415,6 +392,19 @@ export default class SiteStorage {
aggregation.push({
$limit: limit
});
+ // Add Company
+ if (params.withCompany) {
+ DatabaseUtils.pushCompanyLookupInAggregation({
+ tenantID, aggregation, localField: 'companyID', foreignField: '_id',
+ asField: 'company', oneToOneCardinality: true
+ });
+ }
+ // Convert Object ID to string
+ DatabaseUtils.pushConvertObjectIDToString(aggregation, 'companyID');
+ // Add Last Changed / Created
+ DatabaseUtils.pushCreatedLastChangedInAggregation(tenantID, aggregation);
+ // Handle the ID
+ DatabaseUtils.pushRenameDatabaseID(aggregation);
// Project
DatabaseUtils.projectFields(aggregation, projectFields);
// Read DB

MODIFY
src/storage/mongodb/TransactionStorage.ts
src/storage/mongodb/TransactionStorage.ts
@@ -415,9 +415,7 @@ export default class TransactionStorage {
if (ownerMatch.$or && ownerMatch.$or.length > 0) {
aggregation.push({
$match: {
- $and: [
- ownerMatch, filterMatch
- ]
+ $and: [ ownerMatch, filterMatch ]
}
});
} else {
@@ -509,12 +507,12 @@ export default class TransactionStorage {
break;
}
}
- if (transactionCountMDB && transactionCountMDB.countRefundedReports) {
// Translate array response to number
+ if (transactionCountMDB && transactionCountMDB.countRefundedReports) {
transactionCountMDB.countRefundedReports = transactionCountMDB.countRefundedReports.length;
}
- if (transactionCountMDB && transactionCountMDB.currency) {
// Take first entry as reference currency. Expectation is that we have only one currency for all transaction
+ if (transactionCountMDB && transactionCountMDB.currency) {
transactionCountMDB.currency = transactionCountMDB.currency[0];
}
// Check if only the total count is requested
@@ -628,7 +626,6 @@ export default class TransactionStorage {
const ownerMatch = { $or: [] };
const filterMatch = {};
filterMatch['refundData.reportId'] = { '$ne': null };
-
if (params.ownerID) {
ownerMatch.$or.push({
userID: Utils.convertToObjectID(params.ownerID)
@@ -654,9 +651,12 @@ export default class TransactionStorage {
$match: filterMatch
});
}
- aggregation.push(
- { '$group': { '_id': '$refundData.reportId', 'userID': { '$first': '$userID' } } }
- );
+ aggregation.push({
+ $group: {
+ '_id': '$refundData.reportId',
+ 'userID': { '$first': '$userID' }
+ }
+ });
// Limit records?
if (!dbParams.onlyRecordCount) {
// Always limit the nbr of record to avoid perfs issues

MODIFY
src/storage/mongodb/UserStorage.ts
src/storage/mongodb/UserStorage.ts
@@ -650,9 +650,6 @@ export default class UserStorage {
}
// Remove the limit
aggregation.pop();
-
- // Add Created By / Last Changed By
- DatabaseUtils.pushCreatedLastChangedInAggregation(tenantID, aggregation);
// Sort
if (dbParams.sort) {
aggregation.push({
@@ -671,6 +668,8 @@ export default class UserStorage {
aggregation.push({
$limit: limit
});
+ // Add Created By / Last Changed By
+ DatabaseUtils.pushCreatedLastChangedInAggregation(tenantID, aggregation);
// Project
DatabaseUtils.projectFields(aggregation, projectFields);
// Read DB
@@ -728,7 +727,6 @@ export default class UserStorage {
const limit = Utils.checkRecordLimit(dbParams.limit);
// Check Skip
const skip = Utils.checkRecordSkip(dbParams.skip);
-
// Create Aggregation
const aggregation = [];
if (params) {
@@ -771,7 +769,6 @@ export default class UserStorage {
}
// Remove the limit
aggregation.pop();
-
if (dbParams.sort) {
aggregation.push({
$sort: dbParams.sort
@@ -922,7 +919,7 @@ export default class UserStorage {
const uniqueTimerID = Logging.traceStart(MODULE_NAME, 'deleteUser');
// Check Tenant
await Utils.checkTenant(tenantID);
- // Delete User from sites
+ // Delete Site Users
await global.database.getCollection<any>(tenantID, 'siteusers')
.deleteMany({ 'userID': Utils.convertToObjectID(id) });
// Delete Image
@@ -968,8 +965,7 @@ export default class UserStorage {
$match: filters
});
// Get Sites
- DatabaseUtils.pushSiteLookupInAggregation(
- {
+ DatabaseUtils.pushSiteLookupInAggregation({
tenantID, aggregation, localField: 'siteID', foreignField: '_id',
asField: 'site', oneToOneCardinality: true, oneToOneCardinalityNotNull: true
});
@@ -977,15 +973,10 @@ export default class UserStorage {
if (params.search) {
aggregation.push({
$match: {
- $or: [
- { 'site.name': { $regex: params.search, $options: 'i' } }
- ]
+ 'site.name': { $regex: params.search, $options: 'i' }
}
});
}
- // Convert IDs to String
- DatabaseUtils.pushConvertObjectIDToString(aggregation, 'userID');
- DatabaseUtils.pushConvertObjectIDToString(aggregation, 'siteID');
// Limit records?
if (!dbParams.onlyRecordCount) {
// Always limit the nbr of record to avoid perfs issues
@@ -1022,6 +1013,11 @@ export default class UserStorage {
aggregation.push({
$limit: limit
});
+ // Handle the ID
+ DatabaseUtils.pushRenameDatabaseID(aggregation);
+ // Convert IDs to String
+ DatabaseUtils.pushConvertObjectIDToString(aggregation, 'userID');
+ DatabaseUtils.pushConvertObjectIDToString(aggregation, 'siteID');
// Project
DatabaseUtils.projectFields(aggregation, projectFields);
// Read DB
@@ -1029,27 +1025,14 @@ export default class UserStorage {
.aggregate(aggregation, {
collation: { locale: Constants.DEFAULT_LOCALE, strength: 2 },
allowDiskUse: true
- })
- .toArray();
- // Create
- const sites: SiteUser[] = [];
- for (const siteUserMDB of siteUsersMDB) {
- if (siteUserMDB.site) {
- sites.push({
- siteAdmin: siteUserMDB.siteAdmin,
- siteOwner: siteUserMDB.siteOwner,
- userID: siteUserMDB.userID,
- site: siteUserMDB.site
- });
- }
- }
+ }).toArray();
// Debug
Logging.traceEnd(MODULE_NAME, 'UserStorage', uniqueTimerID, { userID: params.userID });
// Ok
return {
count: (sitesCountMDB.length > 0 ?
(sitesCountMDB[0].count === Constants.DB_RECORD_COUNT_CEIL ? -1 : sitesCountMDB[0].count) : 0),
- result: sites
+ result: siteUsersMDB
};
}

MODIFY
test/api/OCPPCommonTests.ts
test/api/OCPPCommonTests.ts
@@ -1120,7 +1120,7 @@ export default class OCPPCommonTests {
'meterStart': meterStart,
'userID': this.transactionStartUser.id,
'siteAreaID': this.chargingStationContext.getChargingStation().siteAreaID,
- 'siteID': this.chargingStationContext.getChargingStation().siteArea.siteID,
+ 'siteID': this.chargingStationContext.getChargingStation().siteArea ? this.chargingStationContext.getChargingStation().siteArea.siteID : null,
'user': {
'id': this.transactionStartUser.id,
'name': this.transactionStartUser.name,

Fixed perfs issue in lookups before sorting + bug in lookup and ID renaming in MongoDB