Skip to content

Commit

Permalink
chore refactor search functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
mwibutsa committed Jun 19, 2019
1 parent 0010feb commit 8f41a87
Show file tree
Hide file tree
Showing 3 changed files with 146 additions and 24 deletions.
137 changes: 123 additions & 14 deletions controllers/search.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import Sequelize from 'sequelize';
import debug from 'debug';
import model from '../models/index';
import helper from '../helpers/helper';

const { createSearchKeyword } = helper;
const { article: articleModel, user: UserModel } = model;

const logError = debug('app:*');
Expand All @@ -11,50 +13,157 @@ const logError = debug('app:*');
*/
class Search {
/**
* @author: Innocent Nkunzi
* @param {*} req character
* @param {*} res array
* @returns {*} match
*/
* @author: Innocent Nkunzi
* @param {*} req character
* @param {*} res array
* @returns {*} match
*/
static async systemSearch(req, res) {
const { keyword, tag, author } = req.query;
let { keyword, tag, author } = req.query;
keyword = createSearchKeyword(keyword);
tag = createSearchKeyword(tag);
author = createSearchKeyword(author);
const { Op } = Sequelize;
try {
const searchTag = await articleModel.findAll({
attributes: { exclude: ['id', 'slug', 'title', 'body', 'authorid', 'views', 'image', 'createdAt', 'updatedAt'] },
attributes: {
exclude: ['id', 'authorid'],
},
where: {
taglist: {
[Op.contains]: [tag],
},
},
});
const searchAuthor = await UserModel.findAll({
attributes: { exclude: ['id', 'password', 'provider', 'provideruserid', 'verified', 'inapp_notifications', 'email_notifications', 'role', 'createdAt', 'updatedAt'] },
attributes: {
exclude: [
'id',
'password',
'provider',
'provideruserid',
'verified',
'inapp_notifications',
'email_notifications',
'role',
'createdAt',
'updatedAt',
],
},
where: {
[Op.or]: {
firstname: { [Op.like]: `%${author}%` }, lastname: { [Op.like]: `%${author}%` }, username: { [Op.like]: `%${author}%` }, email: { [Op.like]: `%${author}%` }, bio: { [Op.like]: `%${author}%` }, image: { [Op.like]: `%${author}%` },
firstname: {
[Op.iLike]: {
[Op.any]: author,
},
},
lastname: {
[Op.iLike]: {
[Op.any]: author,
},
},
username: {
[Op.iLike]: {
[Op.any]: author,
},
},
email: {
[Op.iLike]: {
[Op.any]: author,
},
},
bio: {
[Op.iLike]: {
[Op.any]: author,
},
},
image: {
[Op.iLike]: {
[Op.any]: author,
},
},
},
},
});

const searchArticle = await articleModel.findAll({
attributes: { exclude: ['id', 'provider', 'provideruserid', 'password', 'createdAt', 'updatedAt'] },
include: [{
model: UserModel,
attributes: {
exclude: ['password'],
},
},],
where: {
[Op.or]: {
title: { [Op.like]: `%${keyword}%` }, slug: { [Op.like]: `%${keyword}%` }, body: { [Op.like]: `%${keyword}%` }, description: { [Op.like]: `%${keyword}%` },
title: {
[Op.iLike]: {
[Op.any]: keyword,
},
},
slug: {
[Op.iLike]: {
[Op.any]: keyword,
},
},
body: {
[Op.iLike]: {
[Op.any]: keyword,
},
},
description: {
[Op.iLike]: {
[Op.any]: keyword,
},
},
},
},
});
const searchUser = await UserModel.findAll({
attributes: { exclude: ['id', 'provider', 'provideruserid', 'password', 'createdAt', 'updatedAt'] },
attributes: {
exclude: [
'id',
'provider',
'provideruserid',
'password',
'createdAt',
'updatedAt',
],
},
where: {
[Op.or]: {
firstname: { [Op.like]: `%${keyword}%` }, lastname: { [Op.like]: `%${keyword}%` }, email: { [Op.like]: `%${keyword}%` }, username: { [Op.like]: `%${keyword}%` }, bio: { [Op.like]: `%${keyword}%` },
firstname: {
[Op.iLike]: {
[Op.any]: keyword,
},
},
lastname: {
[Op.iLike]: {
[Op.any]: keyword,
},
},
email: {
[Op.iLike]: {
[Op.any]: keyword,
},
},
username: {
[Op.iLike]: {
[Op.any]: keyword,
},
},
bio: {
[Op.iLike]: {
[Op.any]: keyword,
},
},
},
},
});
return res.status(200).json({
searchArticle, searchUser, searchTag, searchAuthor,
searchArticle,
searchUser,
searchTag,
searchAuthor,
});
} catch (error) {
logError(error);
Expand Down
19 changes: 13 additions & 6 deletions helpers/helper.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,8 @@ const authenticationResponse = (res, token, userData) => res
.json({
user: {
...userData,
token
}
token,
},
});
const articleReadTime = article => Math.ceil(article.split(' ').length / 275);
const combineHelper = (combinedObj, obj2) => ({ ...combinedObj, ...obj2 });
Expand All @@ -78,12 +78,12 @@ const combineWithArticle = (article, ...rest) => {
'description',
'authorid',
'createdAt',
'updatedAt'
'updatedAt',
]);
return {
...articleObject,
...rest.reduce(combineHelper),
readTimeMinutes: articleReadTime(articleObject.body)
readTimeMinutes: articleReadTime(articleObject.body),
};
};
const asyncHandler = callBackFunction => async (req, res, next) => {
Expand All @@ -92,13 +92,19 @@ const asyncHandler = callBackFunction => async (req, res, next) => {
} catch (error) {
const statusCode = error.name === 'SequelizeValidationError' ? 400 : 500;
res.status(statusCode).json({
error: error.message
error: error.message,
});
}
};
const decodeToken = req => jwt.verify(req.header('x-auth-token'), process.env.SECRETKEY);
const jsonResponse = (res, statusCode, message) => res.status(statusCode).json(message);
const compareAction = (action1, action2) => action1 || action2;
const createSearchKeyword = (keyword) => {
keyword = `%${keyword}%`;
keyword = keyword.replace(' ', '% %');
keyword = keyword.split(' ');
return keyword;
};
export default {
hashPassword,
comparePassword,
Expand All @@ -112,5 +118,6 @@ export default {
combineWithArticle,
combineHelper,
jsonResponse,
compareAction
compareAction,
createSearchKeyword,
};
14 changes: 10 additions & 4 deletions test/helper.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ const article = {
description: Carmen Casco de Lara Castro (17 June 1918 – 8 May 1993) was a Paraguayan teacher, women's and human ...`,
authorid: 1,
createdAt: '2019-04-24T09:46:22.945Z',
updatedAt: '2019-04-24T09:46:22.945Z'
updatedAt: '2019-04-24T09:46:22.945Z',
};
describe('Test helpers', () => {
const password = 'PassWord@1!';
Expand Down Expand Up @@ -62,7 +62,7 @@ describe('Test helpers', () => {
const result = helpers.combineWithArticle(article, {
likes: 1,
dislikes: 0,
readTimeMinutes: 1
readTimeMinutes: 1,
});
result.should.have.property('likes');
result.should.have.property('slug');
Expand All @@ -88,9 +88,9 @@ describe('Test helpers', () => {
} catch (err) {
err.name = 'SequelizeValidationError';
}
}
},
};
}
},
};
try {
customFunction(req, res);
Expand All @@ -105,6 +105,12 @@ describe('Test helpers', () => {
.a('string')
.eql('The password must contain at least one lower case character');
});
it('should return be able to create search keyword', () => {
helpers
.createSearchKeyword('Hashed')
.should.be.a('array')
.eql(['%Hashed%']);
});
it('should not allow password withless than 8 characters', () => {
const message = helpers.validatePassword('@1Pass');
message.should.be
Expand Down

0 comments on commit 8f41a87

Please sign in to comment.