241 lines
8.4 KiB
JavaScript
241 lines
8.4 KiB
JavaScript
const advancedResults = (model, populate) => async (req, res, next) => {
|
|
if (req.originalUrl.indexOf('admin') === -1)
|
|
req.query = {
|
|
...req.query,
|
|
$and: [{accessedBy: {$elemMatch: {user: req.user.id}}}],
|
|
}
|
|
|
|
|
|
if (req.query.search === undefined) req.query.search = ''
|
|
if (req.query.search)
|
|
req.query = {...req.query, $text: {$search: req.query.search}}
|
|
|
|
const filterAndInGame = ['genre', 'os', 'developer', 'publisher', 'series', 'intel', 'wine', 'controller', 'store', 'soundtrack', 'playStatus', 'rating', 'ratinggte', 'ratinglte', 'steamRating', 'steamRatinggte', 'steamRatinglte']
|
|
|
|
filterAndInGame.map((filter) => {
|
|
if (req.query[filter] === undefined) req.query[filter] = ''
|
|
if (req.query[filter]) {
|
|
let newFilter
|
|
if (filter === 'os') {
|
|
newFilter = req.query[filter].split(',').reduce((prev, curr, index, arr) => {
|
|
const key = `${[filter]}.${arr[index]}`.toLowerCase()
|
|
prev.push({[key]: true})
|
|
return prev
|
|
}, [])
|
|
} else if (filter === 'store' || filter === 'soundtrack' || filter === 'playStatus') {
|
|
newFilter = req.query[filter].split(',').reduce((prev, curr) => {
|
|
prev.push({accessedBy: {$elemMatch: {[filter]: curr}}})
|
|
return prev
|
|
}, [])
|
|
} else if (filter === 'rating') {
|
|
if (Object.hasOwn(req.query[filter], 'gte')) {
|
|
newFilter = req.query[filter]['gte'].split(',').reduce((prev, curr) => {
|
|
prev.push({accessedBy: {$elemMatch: {rating: {$gte: Number(curr)}}}})
|
|
return prev
|
|
}, [])
|
|
req.query.rating = `gte${req.query[filter]['gte']}`
|
|
} else if (Object.hasOwn(req.query[filter], 'lte')) {
|
|
newFilter = req.query[filter]['lte'].split(',').reduce((prev, curr) => {
|
|
prev.push({accessedBy: {$elemMatch: {rating: {$lte: Number(curr)}}}})
|
|
return prev
|
|
}, [])
|
|
req.query.rating = `lte${req.query[filter]['lte']}`
|
|
} else {
|
|
newFilter = req.query[filter].split(',').reduce((prev, curr) => {
|
|
prev.push({accessedBy: {$elemMatch: {rating: Number(curr)}}})
|
|
return prev
|
|
}, [])
|
|
}
|
|
} else if (filter === 'ratinggte') {
|
|
newFilter = req.query[filter].split(',').reduce((prev, curr) => {
|
|
prev.push({accessedBy: {$elemMatch: {rating: {$gte: Number(curr)}}}})
|
|
return prev
|
|
}, [])
|
|
req.query.rating = req.query.ratinggte
|
|
} else if (filter === 'ratinglte') {
|
|
newFilter = req.query[filter].split(',').reduce((prev, curr) => {
|
|
prev.push({accessedBy: {$elemMatch: {rating: {$lte: Number(curr)}}}})
|
|
return prev
|
|
}, [])
|
|
req.query.rating = req.query.ratinglte
|
|
} else if (filter === 'steamRating') {
|
|
if (Object.hasOwn(req.query[filter], 'gte')) {
|
|
newFilter = req.query[filter]['gte'].split(',').reduce((prev, curr) => {
|
|
prev.push({steamRating: {$gte: Number(curr)}})
|
|
return prev
|
|
}, [])
|
|
req.query.steamRating = `gte${req.query[filter]['gte']}`
|
|
} else if (Object.hasOwn(req.query[filter], 'lte')) {
|
|
newFilter = req.query[filter]['lte'].split(',').reduce((prev, curr) => {
|
|
prev.push({steamRating: {$lte: Number(curr)}})
|
|
return prev
|
|
}, [])
|
|
req.query.steamRating = `lte${req.query[filter]['lte']}`
|
|
} else {
|
|
newFilter = req.query[filter].split(',').reduce((prev, curr) => {
|
|
prev.push({steamRating: Number(curr)})
|
|
return prev
|
|
}, [])
|
|
}
|
|
} else if (filter === 'steamRatinggte') {
|
|
newFilter = req.query[filter].split(',').reduce((prev, curr) => {
|
|
prev.push({steamRating: {$gte: Number(curr)}})
|
|
return prev
|
|
}, [])
|
|
req.query.steamRating = req.query.steamRatinggte
|
|
} else if (filter === 'steamRatinglte') {
|
|
newFilter = req.query[filter].split(',').reduce((prev, curr) => {
|
|
prev.push({steamRating: {$lte: Number(curr)}})
|
|
return prev
|
|
}, [])
|
|
req.query.steamRating = req.query.steamRatinglte
|
|
} else {
|
|
newFilter = req.query[filter].split(',').reduce((prev, curr) => {
|
|
prev.push({[filter]: curr})
|
|
return prev
|
|
}, [])
|
|
}
|
|
newFilter.forEach(element => req.query.$and.push(element))
|
|
}
|
|
})
|
|
|
|
let query
|
|
|
|
// Copy req.query
|
|
const reqQuery = {...req.query}
|
|
|
|
// Fields to exclude
|
|
const removeFields = [
|
|
'select',
|
|
'series',
|
|
'developer',
|
|
'publisher',
|
|
'sort',
|
|
'limit',
|
|
'page',
|
|
'search',
|
|
'os',
|
|
'playStatus',
|
|
'store',
|
|
'soundtrack',
|
|
'genre',
|
|
'controller',
|
|
'rating',
|
|
'ratinggte',
|
|
'ratinglte',
|
|
'steamRating',
|
|
'steamRatinggte',
|
|
'steamRatinglte',
|
|
]
|
|
|
|
// Loop over removeFields and delete them from reqQuery
|
|
removeFields.forEach((param) => delete reqQuery[param])
|
|
|
|
filterAndInGame.forEach((param) => {
|
|
if (req.query[param] === '') delete reqQuery[param]
|
|
})
|
|
|
|
// Create query String
|
|
let queryStr = JSON.stringify(reqQuery)
|
|
|
|
// Create operators like gt, gte, etc...
|
|
queryStr = queryStr.replace(
|
|
/\b(gt|gte|lt|lte|in|all)\b/g,
|
|
(match) => `$${match}`,
|
|
)
|
|
|
|
queryStr = queryStr.replace(/\$\$/g, '$')
|
|
|
|
const total = await model.countDocuments(reqQuery)
|
|
|
|
// Finding resource
|
|
query = model.find(JSON.parse(queryStr))
|
|
|
|
// Select Fields
|
|
if (req.query.select) {
|
|
const fields = req.query.select.split(',').join(' ')
|
|
query = query.select(fields)
|
|
}
|
|
|
|
// Sort
|
|
if (req.query.sort) {
|
|
const sortBy = req.query.sort.split(',').join(' ')
|
|
query = query.sort(sortBy)
|
|
} else {
|
|
query = query.sort('-createDate series title')
|
|
}
|
|
|
|
// Pagination
|
|
let page = parseInt(req.query.page, 10) || 1
|
|
const limit = parseInt(req.query.limit, 10) || 10
|
|
|
|
// This block figures out how many total pages there will be and if
|
|
// the client is calling a page larger than the total pages
|
|
let pages
|
|
if (limit === 1) pages = total
|
|
else if (total === 0) pages = 1
|
|
else if (total % limit === 0) pages = (total - (total % limit)) / limit
|
|
else pages = (total - (total % limit)) / limit + 1
|
|
if (page > pages) page = pages
|
|
|
|
const startIndex = (page - 1) * limit
|
|
const endIndex = page * limit
|
|
|
|
query = query.skip(startIndex).limit(limit)
|
|
|
|
if (populate) {
|
|
query = query.populate(populate)
|
|
}
|
|
|
|
// Executing query
|
|
const results = await query
|
|
|
|
// Pagination result
|
|
const pagination = {}
|
|
|
|
if (endIndex < total) {
|
|
pagination.next = {
|
|
page: page + 1,
|
|
}
|
|
}
|
|
|
|
if (startIndex > 0) {
|
|
pagination.prev = {
|
|
page: page - 1,
|
|
}
|
|
}
|
|
|
|
res.advancedResults = {
|
|
success: true,
|
|
searchParams: req.query.search,
|
|
count: {
|
|
gamesPerPage: results.length,
|
|
totalGames: total,
|
|
currentPage: page,
|
|
pages,
|
|
limit,
|
|
},
|
|
filters: {
|
|
series: req.query.series,
|
|
playStatus: req.query.playStatus,
|
|
genre: req.query.genre,
|
|
os: req.query.os,
|
|
store: req.query.store,
|
|
developer: req.query.developer,
|
|
controller: req.query.controller,
|
|
publisher: req.query.publisher,
|
|
soundtrack: req.query.soundtrack,
|
|
intel: req.query.intel,
|
|
wine: req.query.wine,
|
|
rating: req.query.rating,
|
|
steamRating: req.query.steamRating,
|
|
},
|
|
pagination,
|
|
data: results,
|
|
}
|
|
|
|
next()
|
|
}
|
|
|
|
export default advancedResults
|