Skip to content

Commit

Permalink
Added support for Filter Builder
Browse files Browse the repository at this point in the history
  • Loading branch information
skitsanos committed Oct 24, 2020
1 parent ffb554a commit e9cbc79
Show file tree
Hide file tree
Showing 4 changed files with 135 additions and 17 deletions.
22 changes: 11 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,40 +100,40 @@ Another example - we need to add a ```/api/users``` route that on _GET_ method w
--/echo
----all.js
--/users
----get.js
----post.js
----post.js
```

In other words, file path your API route method handler mirrors your URL path

| **API endpoint** | **Handler** |
| -------------------------------- | --------------------------------- |
| GET /api/echo | /api/echo/get.js |
| GET /api/users | /api/users/get.js |
| GET /api/echo | /api/echo/post.js |
| GET /api/users | /api/users/post.js |
| POST /api/users | /api/users/post.js |
| GET /api/users/_:id_/tasks | /api/users/$id/tasks/get.js |
| GET /api/users/_:id_/tasks/:task | /api/users/$id/tasks/$task/get.js |
| GET /api/users/_:id_/tasks | /api/users/$id/tasks/post.js |
| GET /api/users/_:id_/tasks/:task | /api/users/$id/tasks/$task/post.js |

### Parametrized path

Adding parameters to your URL point handling is pretty simple. Probably, you already noticed from the table above, when we require some parameter, we add its name with $ in front of it in our folder name. Just make sure you don't have duplicating parameters.

| **API endpoint** | **Handler** |
| -------------------------------- | --------------------------------- |
| GET /api/users/_:id_/tasks/:task | /api/users/$id/tasks/$task/get.js |
| GET /api/users/_:id_/tasks/:task | /api/users/$id/tasks/$task/post.js |

```
/foxx/
--/users/
----get.js
----post.js
----post.js
----/$id/
------get.js
------post.js
------/tasks/
--------get.js
--------post.js
--------post.js
--------/$task/
----------get.js
----------post.js
```

More on path parameters you can read on [https://www.arangodb.com/docs/stable/foxx-getting-started.html#parameter-validation](https://www.arangodb.com/docs/stable/foxx-getting-started.html#parameter-validation).
Expand Down Expand Up @@ -214,7 +214,7 @@ Arguments used for context operations:
**Using context utils**

```javascript
//users/$id/get.js
//users/$id/post.js

module.exports = {
contentType: 'application/json',
Expand Down
71 changes: 66 additions & 5 deletions builder/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* @version 1.3.20201023
* @author Skitsanos, [email protected], https://github.com/skitsanos
*/
const {db, query} = require('@arangodb');
const {db, query, aql} = require('@arangodb');
const createRouter = require('@arangodb/foxx/router');
const fs = require('fs');
const path = require('path');
Expand All @@ -15,6 +15,7 @@ const queue = queues.create('default');
const tasks = require('@arangodb/tasks');

const crypto = require('@arangodb/crypto');
const joi = require('joi');

const index = {
foxxServicesLocation: path.join(module.context.basePath, '/foxx'),
Expand Down Expand Up @@ -158,7 +159,7 @@ const index = {
module.context.appRoot = path.join(__dirname, '..');

//get record by id
module.context.get = (store, docId) => query`return document(${db._collection(store)}, ${docId})`;
module.context.get = (store, docId) => query`return unset(document(${db._collection(store)}, ${docId}), "_id", "_rev")`;

//insert new record
module.context.insert = (store, doc) => query`INSERT ${{
Expand All @@ -180,11 +181,12 @@ const index = {
{
return null;
}
const exists = module.context.get(store, docId).toArray()[0];

return exists
const [exists] = module.context.get(store, docId).toArray();

return Boolean(exists)
? query`REMOVE ${docId} IN ${db._collection(store)} RETURN KEEP(OLD, "_key")`
: null;
: {toArray: () => []};
};

module.context.runScript = (scriptName, data, opts) =>
Expand Down Expand Up @@ -244,6 +246,65 @@ const index = {
isEmail(str)
{
return str.match(/^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/);
},

filterBuilder(q = [])
{
const filtersSchema = joi.array().required().items(joi.object({
key: joi.string().required(),
op: joi.string().valid('=', '~', '>', '<', '%').default('='),
value: joi.any()
}));

const validation = filtersSchema.validate(q);
if(validation.error){
throw validation.error;
}

if (q.length === 0)
{
return aql.join([aql``], ' ');
}

const parts = [
aql` FILTER`
];

for (let i = 0; i < q.length; i++)
{
const el = q[i];
switch (el.op)
{
case '~':
parts.push(aql` doc[${el.key}] != ${el.value}`);
break;

case '>':
parts.push(aql`(doc[${el.key}] > ${el.value})`);
break;

case '<':
parts.push(aql` doc[${el.key}] < ${el.value}`);
break;

case '%':
parts.push(aql`LIKE(doc[${el.key}], ${el.value}, true)`);
break;

default:
parts.push(aql`(doc[${el.key}] == ${el.value})`);
break;
}

//parts.push(output);

if (i < q.length - 1 && !Boolean(el.logic))
{
parts.push(aql`&&`);
}
}

return aql.join(parts, ' ');
}
};

Expand Down
58 changes: 58 additions & 0 deletions foxx/examples/complex-query/post.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/**
* Exmaple on how to use FilterBuilder utility
* ArangoDB Foxx Microservices Handler
* @author skitsanos, https://github.com/skitsanos
* @version 1.0.20201023
*/

const joi = require('joi');
const {query} = require('@arangodb');

/*
Payload for POST request:
{
"query": [
{
"key":"email",
"op":"%",
"value": "%skitsanos%"
}
]
}
*/

module.exports = {
contentType: 'application/json',
name: 'Examples - Complex Query via GET',
body: {
model: joi.object({
query: joi.array().required()
}).required()
},
handler: (req, res) =>
{
const {filterBuilder} = module.context.utils;

const {skip, pageSize} = req.queryParams;

const {query: queryPayload} = req.body;

const qb = filterBuilder(queryPayload);

console.log(qb);

const queryResult = query`
LET skip=${skip ? Number(skip) : 0}
LET pageSize=${pageSize ? Number(pageSize) : 25}
for doc in users
${qb}
limit skip,pageSize
return doc
`.toArray();


res.send({result: queryResult});
}
};
1 change: 0 additions & 1 deletion tasks/ga.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ const task = ({clientId, path, headers, context}) =>
params.geoid = headers['x-country'];
}

console.log(params);
request({
method: 'get',
url: 'https://www.google-analytics.com/collect',
Expand Down

0 comments on commit e9cbc79

Please sign in to comment.