Skip to content

Instantly share code, notes, and snippets.

@boydaihungst
Created October 22, 2021 17:13
Show Gist options
  • Save boydaihungst/9adadded8f5b7a8449703f3a3e0e2533 to your computer and use it in GitHub Desktop.
Save boydaihungst/9adadded8f5b7a8449703f3a3e0e2533 to your computer and use it in GitHub Desktop.
public async foldersFilter(
userId: string,
payload: FileFolderInput,
nextCursor?: {
id: string;
sortedValue: any;
},
nextOptions: any = {},
) {
const {
name,
publicStatus,
shareMode,
deleted,
deletedDateFrom,
deletedDateTo,
owner,
ownerAccount,
ownerEmail,
ownerName,
parentFolder,
updatedFrom,
updatedTo,
createdFrom,
createdTo,
sharedWiths,
sortBy,
sortDir,
limit,
} = await foldersFilterValidator.validate(payload);
const user = await this.context.dataSources.userApi.getUserById(userId);
const pipelines = [];
let matchPipeline = {};
if (name) {
// matchPipeline = { $match: { $text: { $search: name } } };
matchPipeline = {
$match: { name: { $regex: name, $options: 'i' } },
};
}
if (owner) {
matchPipeline = merge(matchPipeline, {
$match: { owner: mongoose.Types.ObjectId(owner) },
});
}
if (parentFolder) {
matchPipeline = merge(matchPipeline, {
$match: { parentFolder: mongoose.Types.ObjectId(parentFolder) },
});
}
if (publicStatus) {
matchPipeline = merge(matchPipeline, {
$match: { publicStatus: publicStatus },
});
}
if (shareMode) {
matchPipeline = merge(matchPipeline, {
$match: { shareMode: shareMode },
});
}
if (deleted) {
matchPipeline = merge(matchPipeline, { $match: { deleted: deleted } });
}
if (deletedDateFrom) {
matchPipeline = merge(matchPipeline, {
$match: { deletedDate: { $gte: deletedDateFrom } },
});
}
if (deletedDateTo) {
matchPipeline = merge(matchPipeline, {
$match: { deletedDate: { $lte: deletedDateTo } },
});
}
if (updatedFrom) {
matchPipeline = merge(matchPipeline, {
$match: { updatedAt: { $gte: updatedFrom } },
});
}
if (updatedTo) {
matchPipeline = merge(matchPipeline, {
$match: { updatedAt: { $lte: updatedTo } },
});
}
if (createdFrom) {
matchPipeline = merge(matchPipeline, {
$match: { createdAt: { $gte: createdFrom } },
});
}
if (createdTo) {
matchPipeline = merge(matchPipeline, {
$match: { createdAt: { $lte: createdTo } },
});
}
// ROOT sharing folder
if (!parentFolder && sharedWiths && sharedWiths.length > 0) {
matchPipeline = merge(matchPipeline, {
$match: {
sharedWiths: {
$all: sharedWiths,
},
},
});
}
matchPipeline = merge(matchPipeline, {
$match: { isRoot: false, isTrash: false },
});
if (!isEmpty(matchPipeline)) pipelines.push(matchPipeline);
if (ownerName || ownerEmail || ownerAccount) {
pipelines.push(
{
$lookup: {
from: 'users',
let: { owner: '$owner' },
pipeline: [
{ $match: { $expr: { $eq: ['$_id', '$$owner'] } } },
{
$project: {
_id: 1,
firstName: 1,
lastName: 1,
account: 1,
email: 1,
},
},
{
$addFields: {
fullName: { $concat: ['$firstName', ' ', '$lastName'] },
},
},
],
as: 'owner',
},
},
{ $unwind: '$owner' },
);
}
let ownerPipeline = {};
if (ownerName) {
ownerPipeline = merge(ownerPipeline, {
$match: { 'owner.fullName': { $regex: ownerName, $options: 'i' } },
});
}
if (ownerEmail) {
ownerPipeline = merge(ownerPipeline, {
$match: { 'owner.email': { $regex: ownerEmail, $options: 'i' } },
});
}
if (ownerAccount) {
ownerPipeline = merge(ownerPipeline, {
$match: { 'owner.account': ownerAccount },
});
}
if (!isEmpty(ownerPipeline)) pipelines.push(ownerPipeline);
pipelines.push(
{
$lookup: {
from: 'folders',
let: { parentFolders: '$parentFolders', id: '$_id' },
pipeline: [
{
$match: {
$expr: {
$or: [
{ $in: ['$_id', '$$parentFolders'] },
{ $eq: ['$_id', '$$id'] },
],
},
},
},
],
as: 'parentFolders', // parent includes ca chinh folder + parent folder
},
},
{ $unwind: '$parentFolders' },
);
// guard permission
const guardPipeline = {
$match: {
$or: [
{
// Owner root === userId
$and: [
{ 'parentFolders.owner': mongoose.Types.ObjectId(userId) },
{ 'parentFolders.isRoot': true },
],
},
{ 'parentFolders.publicStatus': PUBLIC_STATUS.PUBLIC },
{
$and: [
{
'parentFolders.sharedWiths': {
$all: [user.email, ...(sharedWiths || [])],
},
},
{
$or: [
{ 'parentFolders.shareMode': SHARE_MODE.VIEWONLY }, // viewonly
{ 'parentFolders.shareMode': SHARE_MODE.EDITABLE }, // editable
],
},
],
},
],
},
};
pipelines.push(guardPipeline);
// deduplicated
pipelines.push({
$group: {
_id: '$_id',
icon: { $first: '$icon' },
color: { $first: '$color' },
isRoot: { $first: '$isRoot' },
isTrash: { $first: '$isTrash' },
deleted: { $first: '$deleted' },
publicStatus: { $first: '$publicStatus' },
sharedWiths: { $first: '$sharedWiths' },
shareMode: { $first: '$shareMode' },
deletedDate: { $first: '$deletedDate' },
keepTrashUntilDate: { $first: '$keepTrashUntilDate' },
name: { $first: '$name' },
owner: { $first: '$owner' },
lastModifier: { $first: '$lastModifier' },
parentFolder: { $first: '$parentFolder' },
createdAt: { $first: '$createdAt' },
updatedAt: { $first: '$updatedAt' },
},
});
//
let sortVal = '';
let sortDirVal = sortDir.valueOf();
if (sortBy) {
switch (sortBy) {
case FILE_SORT_BY.NAME:
sortVal = 'name';
break;
case FILE_SORT_BY.LAST_MODIFIED:
sortVal = 'updatedAt';
break;
default:
sortDirVal = SORT_DIRECTION.ASC.valueOf();
sortVal = 'name';
}
}
let sortPipeline = {};
sortPipeline = merge(sortPipeline, {
$sort: { [sortVal]: sortDirVal },
});
pipelines.push(sortPipeline);
const cursorPipeline = [];
// has next Id
if (nextCursor) {
cursorPipeline.unshift({
$match: {
$or: [
{ [sortVal]: { $gt: nextCursor.sortedValue } },
{
[sortVal]: nextCursor.sortedValue,
_id: { $gt: mongoose.Types.ObjectId(nextCursor.id) },
},
],
},
});
}
const result: {
hasMore: boolean;
total: number;
results: any[];
next: string;
isNextFolder: boolean;
}[] = await FolderModel.aggregate<any>(pipelines)
.facet({
hasMore: [
...cursorPipeline,
{ $count: 'count' },
{
$project: {
hasMore: {
$switch: {
branches: [
{
case: {
$gt: ['$count', limit],
},
then: true,
},
{
case: {
$lte: ['$count', limit],
},
then: false,
},
],
default: false,
},
},
},
},
],
total: [{ $count: 'count' }],
results: [
...cursorPipeline,
{ $limit: limit },
{
$lookup: {
from: 'filefolderfavorites',
let: { id: '$_id' },
pipeline: [
{
$match: {
$expr: { $eq: ['$folder', '$$id'] },
},
},
],
as: 'favorite',
},
},
{
$addFields: {
isFavorite: {
$cond: {
if: {
$gte: [{ $size: '$favorite' }, 1],
},
then: true,
else: false,
},
},
},
},
],
})
.unwind('$hasMore', '$total')
.addFields({
hasMore: '$hasMore.hasMore',
total: '$total.count',
})
.exec();
const lastItem = result[0]?.results[result[0].results.length - 1];
return !lastItem
? {
hasMore: false,
total: result[0]?.total || 0,
results: [],
next: null,
isNextFolder: false,
}
: {
...result[0],
next: result[0].hasMore
? objectToHash(
merge(
{
payload,
lastItem: {
id: lastItem?._id,
sortedValue: lastItem?.[sortVal],
},
isNextFolder: result[0].hasMore,
},
nextOptions,
),
)
: null,
isNextFolder: result[0].hasMore,
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment