[FIX] livechat/rooms endpoint not working with big amount of livechats (#16623)

* Remove aggregate to improve performance

* Use a cursor to run query only once

* Do not use toArray in model

Co-authored-by: Diego Sampaio <chinello@gmail.com>
pull/16188/head^2
Marcos Spessatto Defendi 6 years ago committed by GitHub
parent d1bc646c3c
commit f86323f346
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 33
      app/livechat/server/api/lib/rooms.js
  2. 6
      app/models/server/raw/LivechatDepartment.js
  3. 58
      app/models/server/raw/LivechatRooms.js

@ -1,4 +1,4 @@
import { LivechatRooms } from '../../../../models/server/raw';
import { LivechatRooms, LivechatDepartment } from '../../../../models/server/raw';
export async function findRooms({
agents,
@ -16,18 +16,7 @@ export async function findRooms({
sort,
},
}) {
const total = (await LivechatRooms.findRoomsWithCriteria({
agents,
roomName,
departmentId,
open,
createdAt,
closedAt,
tags,
customFields,
})).length;
const rooms = await LivechatRooms.findRoomsWithCriteria({
const cursor = LivechatRooms.findRoomsWithCriteria({
agents,
roomName,
departmentId,
@ -44,6 +33,24 @@ export async function findRooms({
},
});
const total = await cursor.count();
const rooms = await cursor.toArray();
const departmentsIds = [...new Set(rooms.map((room) => room.departmentId).filter(Boolean))];
if (departmentsIds.length) {
const departments = await LivechatDepartment.findInIds(departmentsIds, { fields: { name: 1 } }).toArray();
rooms.forEach((room) => {
if (!room.departmentId) {
return;
}
const department = departments.find((dept) => dept._id === room.departmentId);
if (department) {
room.department = department;
}
});
}
return {
rooms,
count: rooms.length,

@ -1,6 +1,8 @@
import { BaseRaw } from './BaseRaw';
export class LivechatDepartmentRaw extends BaseRaw {
findInIds(departmentsIds, options) {
const query = { _id: { $in: departmentsIds } };
return this.find(query, options);
}
}

@ -1099,73 +1099,45 @@ export class LivechatRoomsRaw extends BaseRaw {
}
findRoomsWithCriteria({ agents, roomName, departmentId, open, createdAt, closedAt, tags, customFields, options = {} }) {
const match = {
$match: {
t: 'l',
},
const query = {
t: 'l',
};
if (agents) {
match.$match.$or = [{ 'servedBy._id': { $in: agents } }, { 'servedBy.username': { $in: agents } }];
query.$or = [{ 'servedBy._id': { $in: agents } }, { 'servedBy.username': { $in: agents } }];
}
if (roomName) {
match.$match.fname = new RegExp(roomName, 'i');
query.fname = new RegExp(roomName, 'i');
}
if (departmentId) {
match.$match.departmentId = departmentId;
query.departmentId = departmentId;
}
if (open !== undefined) {
match.$match.open = { $exists: open };
query.open = { $exists: open };
}
if (createdAt) {
match.$match.ts = {};
query.ts = {};
if (createdAt.start) {
match.$match.ts.$gte = new Date(createdAt.start);
query.ts.$gte = new Date(createdAt.start);
}
if (createdAt.end) {
match.$match.ts.$lte = new Date(createdAt.end);
query.ts.$lte = new Date(createdAt.end);
}
}
if (closedAt) {
match.$match.closedAt = {};
query.closedAt = {};
if (closedAt.start) {
match.$match.closedAt.$gte = new Date(closedAt.start);
query.closedAt.$gte = new Date(closedAt.start);
}
if (closedAt.end) {
match.$match.closedAt.$lte = new Date(closedAt.end);
query.closedAt.$lte = new Date(closedAt.end);
}
}
if (tags) {
match.$match.tags = { $in: tags };
query.tags = { $in: tags };
}
if (customFields) {
match.$match.$and = Object.keys(customFields).map((key) => ({ [`livechatData.${ key }`]: new RegExp(customFields[key], 'i') }));
}
const sort = { $sort: options.sort || { name: 1 } };
const firstParams = [match, sort];
if (options.offset) {
firstParams.push({ $skip: options.offset });
query.$and = Object.keys(customFields).map((key) => ({ [`livechatData.${ key }`]: new RegExp(customFields[key], 'i') }));
}
if (options.count) {
firstParams.push({ $limit: options.count });
}
const lookup = {
$lookup: {
from: 'rocketchat_livechat_department',
localField: 'departmentId',
foreignField: '_id',
as: 'department',
},
};
const unwind = {
$unwind: {
path: '$department',
preserveNullAndEmptyArrays: true,
},
};
const params = [...firstParams, lookup, unwind];
if (options.fields) {
params.push({ $project: options.fields });
}
return this.col.aggregate(params).toArray();
return this.find(query, { sort: options.sort || { name: 1 }, skip: options.offset, limit: options.count });
}
}

Loading…
Cancel
Save