From e946a55cf65947135836ed23cc1aeca0efcdf2e8 Mon Sep 17 00:00:00 2001 From: Vytor Calixto <vytorcalixto@gmail.com> Date: Wed, 24 May 2017 11:24:01 -0300 Subject: [PATCH] Add multivalue filters feature --- src/libs/middlewares/reqQueryFields.js | 75 +++++++++++++++++++------- 1 file changed, 56 insertions(+), 19 deletions(-) diff --git a/src/libs/middlewares/reqQueryFields.js b/src/libs/middlewares/reqQueryFields.js index b85e3f00..2b785d45 100644 --- a/src/libs/middlewares/reqQueryFields.js +++ b/src/libs/middlewares/reqQueryFields.js @@ -4,6 +4,21 @@ const log = require(`${libs}/log`)(module); const _ = require('lodash'); +function parseWhereValue(type, value) { + if(type === 'integer') return parseInt(value, 10); + if(type === 'double') return parseFloat(value); + if(type === 'string') return '%'+value+'%'; + if(type === 'boolean') { + if (value.toLowerCase() === 'null') { + console.log('Fazendo uma consulta Null'); + return null; + } else { + console.log('Fazendo uma consulta True'); + return (value.toLowerCase() === 'true' || parseInt(value, 10) === 1); + } + } +} + class ReqQueryFields { constructor(fields = {}, fieldValues = {}) { // Exemplo de requisição: `/api/v1/enrollments?dims=state,region,location` @@ -128,7 +143,8 @@ class ReqQueryFields { if (req.query[queryField]) { // Se há mais de um parametro no campo, eles estão separados por vÃrgula. // Fazemos o split então para separar os valores - const params = req.query[queryField].split(','); + const regex = /,(?=[a-z])/; // Pega as vÃrgulas que não estão nos atributos multivalorados + const params = req.query[queryField].split(regex); // Objeto temporário para guardar os parametros e seus valores. const obj = {}; for (const param of params) { @@ -136,7 +152,7 @@ class ReqQueryFields { // Fazemos o split e temos um array `['state', 41]` const kv = param.split(':'); // Checa se há um valor. Se não tem, definimos como true. - obj[kv[0]] = (typeof kv[1] === 'undefined') ? true : kv[1]; + obj[kv[0]] = (typeof kv[1] === 'undefined') ? true : JSON.parse(kv[1]); // `obj` é agora `{kv[0]: kv[1]}` ou `{kv[0]: true}`. // No exemplo `{'state': 41}` } @@ -177,8 +193,6 @@ class ReqQueryFields { log.debug(field); // `param` aqui é o atributo no objeto `req` (dims, filter, search, ...) let param = req[field.name]; - // log.debug('param'); - // log.debug(param); // Fazemos um foreach nos parametros dentro do atributo Object.keys(param).forEach((k) => { let values = _.merge(this.fieldValues, field.values); @@ -226,19 +240,14 @@ class ReqQueryFields { // Valor do where let whereValue = param[k]; - // Valor sempre vem como string, necessário fazer parse para o banco - if(value.where.type === 'integer') whereValue = parseInt(whereValue, 10); - if(value.where.type === 'double') whereValue = parseFloat(whereValue); - if(value.where.type === 'string') whereValue = '%'+whereValue+'%'; - if(value.where.type === 'boolean') { - if (whereValue.toLowerCase() === 'null') { - whereValue = null; - console.log('Fazendo uma consulta Null'); - } else { - whereValue = (whereValue.toLowerCase() === 'true' || parseInt(whereValue, 10) === 1); - console.log('Fazendo uma consulta True'); - } - } + log.debug('whereValue'); + log.debug(whereValue); + log.debug(`Where value é array? ${Array.isArray(whereValue)}`); + // TODO: | + // TODO: | + // TODO: V + //TODO: parse do valor do where onde apropriado!!!!!!! + let tbl = value.where.table || value.table; // multiple where, only tested for boolean filds if (Array.isArray(value.tableField)) { @@ -246,18 +255,46 @@ class ReqQueryFields { let whereField = ''; let whereValues = []; value.where.field.forEach((f, i, arr) => { - whereValues.push(whereValue); whereField += (value.where.type === 'string') ? 'LOWER(' + tbl + '.' + value.where.field[i] + ')' : tbl + '.' + value.where.field[i]; whereField += ' ' + value.where.relation + ' ?'; if (i < arr.length - 1) { whereField += ' ' + value.where.condition + ' '; } + + if (Array.isArray(whereValue)) { + let whereString = '('; + for(let i = 0; i < whereValue.length; ++i) { + whereString += whereField; + whereValues.push(parseWhereValue(value.where.type, whereValue[i])); + if(i < whereValue.length-1) { + whereString += ' OR '; + } + } + whereString += ')'; + } else { + whereValues.push(parseWhereValue(value.where.type, whereValue)); + } }); + req.sql.where(whereField, ...whereValues); } else { let whereField = (value.where.type === 'string') ? 'LOWER(' + tbl + '.' + value.where.field + ')' : tbl + '.' + value.where.field; let lower = (value.where.type === 'string') ? ' LOWER(?) ' : ' ? '; - req.sql.where(whereField + ' ' + value.where.relation + lower, whereValue); + if(Array.isArray(whereValue)) { + let whereString = '('; + let arrayWhereValues = []; + for(let i = 0; i < whereValue.length; ++i) { + whereString += whereField + ' ' + value.where.relation + lower; + arrayWhereValues.push(parseWhereValue(value.where.type, whereValue[i])); + if(i < whereValue.length-1) { + whereString += ' OR '; + } + } + whereString += ')'; + req.sql.where(whereString, ...arrayWhereValues); + } else { + req.sql.where(whereField + ' ' + value.where.relation + lower, parseWhereValue(value.where.type, whereValue)); + } } } } -- GitLab