4

(sorry for the newbie question, but can't find it easily in documentation)

I want to have a document store with a few models, and then use some of the attributes as parameters in queries, in my Foxx services. Say I have a db for movies and series episodes:

{
    'type':'movie',
    'year':'1997',
    'director':'xxxxxxx',
    ...
},
{
    'type':'series_episode',
    'season':'1',
    'episode':'3',
    ...
}
...

I need to be able to search on

Of course what I would like to do is to have a single router that would support both GET /?type=movie&year=x&director=y.. GET /?type=series&season=x&episode=y Is that possible? Easy to do?

I couldn't find out, so I started thinking that I have to have different routers for each of the types, like this:

router.get('/movies', function (req, res) {
        const data = db._query('FOR entry IN mystore FILTER entry.type == @type, entry.year == @year RETURN entry ', 
        {'type':'movie', .....});
                res.json({
                    result: data
                })
});


router.get('/series', function (req, res) {
        const data = db._query('FOR entry IN mystore FILTER entry.type == @type, entry.season == @season, entry.episode == @episode, RETURN entry ', 
        {'type':'series', .....});
                res.json({
                    result: data
                })
})

That would be heavy work to maintain. Ideally I would just update the models and use one single router.

Even for this last option I had a question: How do i pass more than one parameters to the query? I can't find the syntax.

Any help is appreciated. I am learning ArangoDB and I am very interested in the potential, but I can't navigate around the documentation I saw or examples.

Thank you

1 Answer 1

2

This question is meanwhile covered in the Foxx Manual and in detail in the endpoints documentation.

Query parameters can accessed by specifying queryParam(...)s to the JOI-router definition, and later on in the function body they can be accessed via req.queryParams.yourQueryParam.

Please note that you can use the API-Tab in the webinterface to use swagger to explore your API interactively.

A very simple Foxx service accepting two query parameters could look like this:

'use strict';

const joi = require('joi');

const router = require('@arangodb/foxx/router')();
module.context.use(router);
router.get('/hello/', function (req, res) {
    res.send(JSON.stringify({hello: `world of FirstName: ${req.queryParams.fname} LastName: ${req.queryParams.lname}`}));
})
.queryParam('fname', joi.string().required(), 'First Name to greet.')
.queryParam('lname', joi.string().required(), 'Last Name to greet.')
.response(['text/plain'], 'A personalized greeting.')
.summary('Personalized greeting')
.description('Prints a personalized greeting.');

An invocation could look like this:

curl -X GET "http://127.0.0.1:8529/_db/_system/myfoxx/hello?fname=Joe&lname=Smith"
...
{"hello":"world of FirstName: Joe LastName: Smith"}

In Path parameters could be achieved like this:

'use strict';

const joi = require('joi');

const router = require('@arangodb/foxx/router')();
module.context.use(router);
router.get('/hello/:fname/:lname', function (req, res) {
    res.send(JSON.stringify({hello: `world of FirstName: ${req.pathParams.fname} LastName: ${req.pathParams.lname}`}));
})
.pathParam('fname', joi.string().required(), 'First Name to greet.')
.pathParam('lname', joi.string().required(), 'Last Name to greet.')
.response(['text/plain'], 'A personalized greeting.')
.summary('Personalized greeting')
.description('Prints a personalized greeting.');

And an invocation could be done like this:

curl -X GET "http://127.0.0.1:8529/_db/_system/myfoxx/hello/Joe/Smith" 
...
{"hello":"world of FirstName: Joe LastName: Smith"}
Sign up to request clarification or add additional context in comments.

4 Comments

Thanks, this answers the question. One more thing - my goal is to use these parameters in filters. How do I support optional parameters? e.g. i want to filter on first name OR last name ` router.get('/people', function (req, res) { const keys = db._query(aql' FOR entry IN ${foxxColl} FILTER entry.firstName == ${req.queryParams.fname} FILTER entry.lastName == ${req.queryParams.lname} RETURN entry '); res.send(keys); }) .queryParam('fname', joi.string().optional(), 'First Name.') .queryParam('lname', joi.string().optional(), 'Last Name.') ...`
@costateixeira you could either do something like FILTER !${req.queryParams.fname} || entry.firstName == ${req.queryParams.fname} (i.e. explicitly check if the param is even set) or you could build the filters using the aql helper methods (nesting aql templates and using aql.join): arangodb.com/docs/stable/…
thanks @AlanPlum but if i do FILTER !${req.queryParams.fname} || entry.firstName == ${req.queryParams.fname} i get unexpected or operator near '|| entry.firstName == \n\t\tFILTER ...' at position 3:12 (while parsing) - i guess if the parameter is null, the line in not syntactically correct..? The aql.join would be good if i can make it work. is there any example of how to conditionally define a filter? again, sorry for the noob question. thanks!
@costateixeira Ah, sorry, I misread. Undefined values will be ignored. Try defaulting the value to null. E.g. const {fname = null} = req.queryParams; and then using fname instead of req.queryParams.fname. With joi joi.string().optional().default(null) should also work, I think.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.