Browse Source

Feature : adding 'range' option to Chart API npm v0.3.1

pull/13/head
oof1lab 7 years ago
parent
commit
bf95f02c75
  1. 55
      README.md
  2. 2
      lib/util/cmd.helper.js
  3. 4
      lib/util/data.helper.js
  4. 20
      lib/xapi.js
  5. 31
      lib/xsql.js
  6. 2
      package.json
  7. 68
      tests/tests.js

55
README.md

@ -73,7 +73,7 @@ Powered by popular node packages : ([express](https://github.com/expressjs/expre
* Group By, Having (as query params) :fire::fire: * Group By, Having (as query params) :fire::fire:
* Group By, Having (as a separate API) :fire::fire: * Group By, Having (as a separate API) :fire::fire:
* Multiple group by in one API :fire::fire: * Multiple group by in one API :fire::fire:
* Chart API for numeric column :fire::fire: * Chart API for numeric column :fire::fire::fire::fire::fire::fire:
* Supports views * Supports views
* Prototyping (features available when using local MySql server only) * Prototyping (features available when using local MySql server only)
* Run dynamic queries :fire::fire::fire: * Run dynamic queries :fire::fire::fire:
@ -431,11 +431,11 @@ response body
## Chart ## Chart
[:arrow_heading_up:](#api-overview) [:arrow_heading_up:](#api-overview)
:fire::fire: **[ HOTNESS ALERT ]** :fire::fire::fire::fire::fire::fire: **[ HOTNESS ALERT ]**
Chart API returns distribution of a numeric column in a table Chart API returns distribution of a numeric column in a table
It comes in three flavours It comes in **SIX** powerful flavours
1. Chart : With min, max, step in query params :fire::fire: 1. Chart : With min, max, step in query params :fire::fire:
[:arrow_heading_up:](#api-overview) [:arrow_heading_up:](#api-overview)
@ -550,6 +550,55 @@ Response
``` ```
4. Chart : With min, max, step in query params :fire::fire:
[:arrow_heading_up:](#api-overview)
This API returns the number of rows where amount is between (0,25000), (0,50000) ... (0,maxValue)
Number of records for amount is calculated everytime from min value to extended Range instead of incremental steps
```
/api/payments/chart?_fields=amount&min=0&max=131000&step=25000&range=1
Response
[
{
"amount": "0 to 25000",
"_count": 107
},
{
"amount": "0 to 50000",
"_count": 231
},
{
"amount": "0 to 75000",
"_count": 261
},
{
"amount": "0 to 100000",
"_count": 268
},
{
"amount": "0 to 125000",
"_count": 273
}
]
```
5. Range can be specified to other variations of chart operation #2 and #3 like below
```
/api/payments/chart?_fields=amount&steparray=0,10000,20000,70000,140000
```
6.
```
/api/payments/chart?_fields=amount&range=1
```
Please Note: Please Note:
_fields in Chart API can only take numeric column as its argument. _fields in Chart API can only take numeric column as its argument.

2
lib/util/cmd.helper.js

@ -11,7 +11,7 @@ program.on('--help', () => {
}) })
program program
.version('0.3.0') .version('0.3.1')
.option('-h, --host <n>', 'hostname / localhost by default') .option('-h, --host <n>', 'hostname / localhost by default')
.option('-u, --user <n>', 'username of database / root by default') .option('-u, --user <n>', 'username of database / root by default')
.option('-p, --password <n>', 'password of database / empty by default') .option('-p, --password <n>', 'password of database / empty by default')

4
lib/util/data.helper.js

@ -66,7 +66,7 @@ exports.numberGetFixed = (number) => {
return parseInt(number.toFixed()) return parseInt(number.toFixed())
} }
exports.getRangeSimple = function (min, max, step) { exports.getStepArraySimple = function (min, max, step) {
var arr = [] var arr = []
for (var i = min; i <= max; i = i + step) { for (var i = min; i <= max; i = i + step) {
@ -77,7 +77,7 @@ exports.getRangeSimple = function (min, max, step) {
}; };
exports.getRange = (min, max, stddev) => { exports.getStepArray = (min, max, stddev) => {
// console.log(' = = = = = = = '); // console.log(' = = = = = = = ');
//console.log('original numbers', min, max, stddev); //console.log('original numbers', min, max, stddev);

20
lib/xapi.js

@ -772,7 +772,16 @@ class Xapi {
let params = [] let params = []
let obj = {} let obj = {}
if (req.query && req.query._fields) {
if (req.query) {
let isRange = false
if (req.query.range) {
isRange = true
}
if (req.query && req.query.min && req.query.max && req.query.step) { if (req.query && req.query.min && req.query.max && req.query.step) {
@ -782,14 +791,16 @@ class Xapi {
req.query._fields, req.query._fields,
parseInt(req.query.min), parseInt(req.query.min),
parseInt(req.query.max), parseInt(req.query.max),
parseInt(req.query.step)) parseInt(req.query.step),
isRange)
} else if (req.query && req.query.steparray && req.query.steparray.length > 1) { } else if (req.query && req.query.steparray && req.query.steparray.length > 1) {
obj = this.mysql.getChartQueryAndParamsFromStepArray(req.app.locals._tableName, obj = this.mysql.getChartQueryAndParamsFromStepArray(req.app.locals._tableName,
req.query._fields, req.query._fields,
(req.query.steparray.split(',')).map(Number)) (req.query.steparray.split(',')).map(Number),
isRange)
} else { } else {
@ -814,7 +825,8 @@ class Xapi {
req.query._fields, req.query._fields,
results[0]['min'], results[0]['min'],
results[0]['max'], results[0]['max'],
results[0]['stddev'] results[0]['stddev'],
isRange
) )
} }

31
lib/xsql.js

@ -592,16 +592,16 @@ class Xsql {
} }
getChartQueryAndParamsFromStepArray(tableName, columnName, stepArray) { getChartQueryAndParamsFromStepArray(tableName, columnName, stepArray, isRange = false) {
let obj = {} let obj = {}
obj.query = '' obj.query = ''
obj.params = [] obj.params = []
if (stepArray.length && stepArray.length >= 2) { //console.log('getChartQueryAndParamsFromStepArray',isRange);
let params = [tableName, columnName, stepArray[0], stepArray[1]] if (stepArray.length && stepArray.length >= 2) {
for (let i = 0; i < stepArray.length - 1; i = i + 1) { for (let i = 0; i < stepArray.length - 1; i = i + 1) {
@ -610,16 +610,27 @@ class Xsql {
obj.query = obj.query + ' union ' obj.query = obj.query + ' union '
} }
if (i) { if (i && isRange === false) {
stepArray[i] = stepArray[i] + 1 stepArray[i] = stepArray[i] + 1
} }
if (isRange === false) {
obj.params.push((stepArray[i]) + ' to ' + stepArray[i + 1]) obj.params.push((stepArray[i]) + ' to ' + stepArray[i + 1])
} else {
obj.params.push((stepArray[0]) + ' to ' + stepArray[i + 1])
}
obj.params.push(columnName) obj.params.push(columnName)
obj.params.push(tableName) obj.params.push(tableName)
obj.params.push(columnName) obj.params.push(columnName)
if (isRange === false) {
obj.params.push(stepArray[i]) obj.params.push(stepArray[i])
obj.params.push(stepArray[i + 1]) obj.params.push(stepArray[i + 1])
} else {
obj.params.push(stepArray[0])
obj.params.push(stepArray[i + 1])
}
} }
@ -632,13 +643,13 @@ class Xsql {
} }
getChartQueryAndParamsFromMinMaxStddev(tableName, columnName, min, max, stddev) { getChartQueryAndParamsFromMinMaxStddev(tableName, columnName, min, max, stddev, isRange = false) {
let stepArray = dataHelp.getRange(min, max, stddev) let stepArray = dataHelp.getStepArray(min, max, stddev)
//console.log('steparray', stepArray); //console.log('steparray', stepArray);
let obj = this.getChartQueryAndParamsFromStepArray(tableName, columnName, stepArray) let obj = this.getChartQueryAndParamsFromStepArray(tableName, columnName, stepArray, isRange)
//console.log('steparray', obj); //console.log('steparray', obj);
@ -646,13 +657,13 @@ class Xsql {
} }
getChartQueryAndParamsFromMinMaxStep(tableName, columnName, min, max, step) { getChartQueryAndParamsFromMinMaxStep(tableName, columnName, min, max, step, isRange = false) {
let stepArray = dataHelp.getRangeSimple(min, max, step) let stepArray = dataHelp.getStepArraySimple(min, max, step)
//console.log('steparray', stepArray); //console.log('steparray', stepArray);
let obj = this.getChartQueryAndParamsFromStepArray(tableName, columnName, stepArray) let obj = this.getChartQueryAndParamsFromStepArray(tableName, columnName, stepArray, isRange)
//console.log('steparray', obj); //console.log('steparray', obj);

2
package.json

@ -1,6 +1,6 @@
{ {
"name": "xmysql", "name": "xmysql",
"version": "0.3.0", "version": "0.3.1",
"description": "One command to generate REST APIs for any MySql database", "description": "One command to generate REST APIs for any MySql database",
"main": "index.js", "main": "index.js",
"scripts": { "scripts": {

68
tests/tests.js

@ -783,7 +783,8 @@ describe('xmysql : tests', function () {
}); });
}); });
// something weird going on // SOMETHING WEIRD HERE
// test in travis show 7 but on local machine result has 6 elements
// it('GET /api/productlines?_where=(htmlDescription,is,null) should PASS', function (done) { // it('GET /api/productlines?_where=(htmlDescription,is,null) should PASS', function (done) {
// //
// //post to an url with data // //post to an url with data
@ -1203,6 +1204,28 @@ describe('xmysql : tests', function () {
}); });
}) })
it('GET /api/payments/chart?_fields=amount&min=0&max=131000&step=25000&range=1 should PASS', function (done) {
//post to an url with data
agent.get('/api/payments/chart?_fields=amount&min=0&max=131000&step=25000&range=1') //enter url
.expect(200)//200 for success 4xx for failure
.end(function (err, res) {
// Handle /api/v error
if (err) {
return done(err);
}
res.body.length.should.be.equals(5)
res.body[4]['_count'].should.be.equals(273)
res.body[1]['_count'].should.be.equals(231)
res.body[0]['_count'].should.be.equals(107)
return done();
});
})
it('GET /api/payments/chart?_fields=amount&steparray=0,50000,100000,140000 should PASS', function (done) { it('GET /api/payments/chart?_fields=amount&steparray=0,50000,100000,140000 should PASS', function (done) {
//post to an url with data //post to an url with data
@ -1224,6 +1247,47 @@ describe('xmysql : tests', function () {
}); });
}) })
it('GET /api/payments/chart?_fields=amount&steparray=0,50000,100000,140000&range=1 should PASS', function (done) {
//post to an url with data
agent.get('/api/payments/chart?_fields=amount&steparray=0,50000,100000,140000&range=1') //enter url
.expect(200)//200 for success 4xx for failure
.end(function (err, res) {
// Handle /api/v error
if (err) {
return done(err);
}
res.body.length.should.be.equals(3)
res.body[0]['_count'].should.be.equals(231)
res.body[1]['_count'].should.be.equals(268)
res.body[2]['_count'].should.be.equals(273)
return done();
});
})
it('GET /api/payments/chart?_fields=amount&range=1 should PASS', function (done) {
//post to an url with data
agent.get('/api/payments/chart?_fields=amount&range=1') //enter url
.expect(200)//200 for success 4xx for failure
.end(function (err, res) {
// Handle /api/v error
if (err) {
return done(err);
}
res.body.length.should.be.equals(7)
res.body[0]['_count'].should.be.equals(45)
res.body[6]['_count'].should.be.equals(273)
return done();
});
})
it('GET /api/offices/1/employees?_groupby=jobTitle&_having=(_count,gt,1) should PASS', function (done) { it('GET /api/offices/1/employees?_groupby=jobTitle&_having=(_count,gt,1) should PASS', function (done) {
//post to an url with data //post to an url with data
@ -1823,8 +1887,6 @@ describe('xmysql : tests', function () {
var err = whereClause.getConditionClause('(a,is,null)~and(b,is,true)~and(c,is,false)') var err = whereClause.getConditionClause('(a,is,null)~and(b,is,true)~and(c,is,false)')
//console.log(err.params[1],err);
err.err.should.be.equal(0) err.err.should.be.equal(0)
err.query.should.be.equal('(?? is ?)and(?? is ?)and(?? is ?)') err.query.should.be.equal('(?? is ?)and(?? is ?)and(?? is ?)')
//err.params[1].should.be.equal(null) //err.params[1].should.be.equal(null)

Loading…
Cancel
Save