arangodbfoxxarangodb-foxx

Body parameter in ArangoDB


I wrote the following router in Foxx Microservices:

router.post('/PersonInformation', function (req, res) {
    const keys = db._query(aql`
    FOR p IN Personal
                FILTER (p.stateId IN ${req.queryParams.statePar} OR IS_NULL(${req.queryParams.statePar}))
                AND p.empDate >= TO_NUMBER(${req.queryParams.fromDatePar}) AND p.empDate <= TO_NUMBER(${req.queryParams.toDatePar})
                          RETURN p
  `);
  res.send(keys);
  })
  .queryParam('statePar', joi.array().default(null), 'State Parameter')
  .queryParam ('fromDatePar', joi.string().required(), 'FromDate Parameter')
  .queryParam('toDatePar', joi.string().required(), 'ToDate Parameter')
  .response(joi.array().items(
  joi.string().required()
  ).required(), 'List of entry keys.')
  .summary('List entry keys')
  .description('Assembles a list of keys of entries in the collection.');

How i can convert queryParam to body parameter. I used .body instead of .queryParam, but it does not answer. I also wrote the table as follows, but it still does not work:

router.post('/PersonInformation', function (req, res) {
  const distributorIdPar = req.body;
  const cityPar = req.body;
  const productIdPar = req.body;
  const fromDatePar = req.body;
  const toDatePar = req.body;
  const keys = db._query(aql`
    const keys = db._query(aql`
    FOR p IN Personal
                FILTER (p.stateId IN ${req.body.statePar} OR IS_NULL(${req.body.statePar}))
                AND p.empDate >= TO_NUMBER(${req.body.fromDatePar}) AND p.empDate <= TO_NUMBER(${req.body.toDatePar})
                          RETURN p
  `);
  res.send(keys);
  })
  .response(joi.array().items(
  joi.string().required()
  ).required(), 'List of entry keys.')
  .summary('List entry keys')
  .description('Assembles a list of keys of entries in the collection.');

Solution

  • You have a duplicate line const keys = db._query(aql` that breaks the syntax. Furthermore, you are not setting .body(joi.object()) or .body(['application/json']), which leads to req.body being a Buffer:

    If no body has been defined for the current route, the value will be identical to rawBody – docs

    You also assign req.body to various variables but don't actually use them.

    I would assign the body parameters to local variables using destructuring for the guaranteed values, and use a regular assignment for statePar so that it can default to null if it is omitted from the body. Furthermore, I would enforce numeric values for fromDatePar and toDatePar (note that this requires strict() in joi or it will happily accept number strings) and remove TO_NUMBER() from the query. Below code accepts either an array of strings for statePar or expects the attribute to not be present. It disallows "statePar":null, "statePar":[], and "statePar":[null], but you could change that if desired.

    'use strict';
    const joi = require('joi');
    const { db, aql } = require('@arangodb');
    const createRouter = require('@arangodb/foxx/router');
    const router = createRouter();
    
    router.post('/PersonInformation', function (req, res) {
      const statePar = req.body.statePar || null;
      const { fromDatePar, toDatePar } = req.body;
      const keys = db._query(aql`
        FOR p IN Personal
          FILTER (p.stateId IN ${statePar} OR IS_NULL(${statePar}))
          AND p.empDate >= ${fromDatePar} AND p.empDate <= ${toDatePar}
          RETURN p
      `);
      res.send(keys);
    })
    .body(joi.object({
      statePar: joi.array().items(
        joi.string().required()
      ),
      fromDatePar: joi.number().required(),
      toDatePar: joi.number().required(),
    }).required().strict(), 'Search parameters')
    .response(joi.array().items(
      joi.string().required()
    ).required(), 'List of entry keys.')
    .summary('List entry keys')
    .description('Assembles a list of keys of entries in the collection.');
    
    module.context.use(router);