aql.literal не является функцией в arangoDB Foxx - PullRequest
0 голосов
/ 21 ноября 2018

У меня есть маршрут Foxx, подобный следующему

 const aql = require('@arangodb').aql;

    route.get('ABC'){function(req,res){
    //Do some stuffs
    var AnArray1=req.queryParams.AnArray1||[DefaulArray]
    var AnArray2=req.queryParams.AnArray2||[DefaulArray]

    //Turn them into segment to put into AQL
 var segment=aql.literal(AnArray1.length>0 ? 'AND  u.Code IN '+ JSON.stringify(AnArray1)  : '');

    }
    .queryParam('AnArray1', joi.any())
    .queryParam('AnArray2', joi.any())
    .response(['json/application'], 'Done task')

Это отбрасывает aql.literal is not a function.Это очень странно для меня, так как я думал, что это встроенный. Версия arango - 3.3.5

Где я ошибся?

1 Ответ

0 голосов
/ 22 ноября 2018

v3.3.5 исполнилось 8 месяцев (выпущено в 2018-03-28), aql.literal было добавлено в v3.3.9 (2018-05-17):

Обновление до последней версии 3.3 (в настоящее время v3.3.17 от 2018-10-04) должно решить проблему.

Как вы используете aql.literal() не выглядит очень безопасным в отношении AnArray1.Не существует проверки схемы, которая бы гарантировала, что это массив (joi.any()), и вы не будете проверять тип в более поздний момент.Строки в действительности будут проходить req.queryParams.AnArray1||[DefaulArray] и AnArray1.length>0, и в итоге вы получите сегмент запроса, такой как AND u.Code IN "some string", который всегда будет false .

Комбинация aql.literal()и JSON.stringify больше не рекомендуется.Начиная с ArangoJS версии 6.7.0 и ArangoDB v3.4.0-RC.2 в Foxx, поддерживается вложенность строк шаблона AQL:

var coll = db.collection('test')
var AnArray1 = [ "foo", 2, -0.1, true, null, [ false, { bar: true } ] ]

var segment = (
  Array.isArray(AnArray1) && AnArray1.length > 0
  ? aql`AND u.Code IN ${AnArray1}`
  : undefined
)
var fullQuery = aql`FOR u IN ${coll} FILTER u.attr == true ${segment} RETURN u`

В результате fullQuery выглядит так:

{
   query: 'FOR u IN @@value0 FILTER u.attr == true AND u.Code IN @value1 RETURN u',
   bindVars: {
     '@value0': 'test',
     value1: [ 'foo', 2, -0.1, true, null, [false, { bar: true } ] ]
   }
}

С var AnArray1 = "foo" вы получите это вместо:

{
  query: 'FOR u IN @@value0 FILTER u.attr == true  RETURN u',
  bindVars: { '@value0': 'test' }
}

Пока вы хотите AND объединить FILTER критерий, я бы предложил использовать

aql`FILTER u.Code IN ${AnArray1}`

, поскольку вы можете использовать этот сегмент в качестве фильтра самостоятельно, тогда как AND ... может быть недействительным в полном запросе (FILTER AND ...).

...