lib/helpers.js
function generateQuery (fields, options, not) {
  let $and = []
  const $or = []
  const result = {}

  for (const key in options)
    switch (key) {
    case 'and':
    case 'or':
      const query = {}
      query[`$${key}`] = mapValues(options[key], value => {
        return generateQuery(fields, value)
      })
      return query
    case 'not':
      return generateQuery(fields, options[key], true)
    case 'range':
      $and.push(generateRangeQuery(fields, options.range))
      break
    case 'match':
      if ('or' in options.match)
        for (const key in options.match.or) {
          const q = {}
          q[key] = options.match.or[key]
          $or.push(q)
        }
      else $and.push(mapValues(options.match, value =>
        Array.isArray(value) ? { $in: value } : value))
      break
    case 'exists':
      $and.push(mapValues(options.exists, (value, key) => {
        if (!(key in fields)) return void 0

        if (fields[key].isArray)
          return value ? { $ne: [] } : []

        return value ? { $ne: null } : null
      }))
      break
    default:
    }

  if (not)
    $and = $and.map(applyNotOperator)

  if ($and.length) result.$and = $and
  if ($or.length) result.$or = $or

  return result
}
function generateQuery (fields, options, not) {
  let $and = []
  const $or = []
  const result = {}

  for (const key in options)
    switch (key) {
    case 'and':
    case 'or':
      const query = {}
      query[`$${key}`] = mapValues(options[key], value => {
        return generateQuery(fields, value)
      })
      return query
    case 'not':
      return generateQuery(fields, options[key], true)
    case 'range':
      $and.push(generateRangeQuery(fields, options.range))
      break
    case 'match':
      if ('or' in options.match)
        for (const key in options.match.or) {
          const q = {}
          q[key] = options.match.or[key]
          $or.push(q)
        }
      else $and.push(mapValues(options.match, value =>
        Array.isArray(value) ? { $in: value } : value))
      break
    case 'exists':
      $and.push(mapValues(options.exists, (value, key) => {
        if (!(key in fields)) return void 0

        if (fields[key].isArray)
          return value ? { $ne: [] } : []

        return value ? { $ne: null } : null
      }))
      break
    default:
    }

  if (not)
    $and = $and.map(applyNotOperator)

  if ($and.length) result.$and = $and
  if ($or.length) result.$or = $or

  return result
}
function generateQuery ( fields , options , not ) { let $and = [ ] const $or = [ ] const result = { } for ( const key in options ) switch ( key ) { case 'and' : case 'or' : const query = { } query [ ` ${ key } ` ] = mapValues ( options [ key ] , value => { return generateQuery ( fields , value ) } ) return query case 'not' : return generateQuery ( fields , options [ key ] , true ) case 'range' : $and . push ( generateRangeQuery ( fields , options . range ) ) break case 'match' : if ( 'or' in options . match ) for ( const key in options . match . or ) { const q = { } q [ key ] = options . match . or [ key ] $or . push ( q ) } else $and . push ( mapValues ( options . match , value => Array . isArray ( value ) ? { $in : value } : value ) ) break case 'exists' : $and . push ( mapValues ( options . exists , ( value , key ) => { if ( ! ( key in fields ) ) return void 0 if ( fields [ key ] . isArray ) return value ? { $ne : [ ] } : [ ] return value ? { $ne : null } : null } ) ) break default : } if ( not ) $and = $and . map ( applyNotOperator ) if ( $and . length ) result . $and = $and if ( $or . length ) result . $or = $or return result }
Generate a mongoDB query from a fortune query object
Generate a mongoDB query from a fortune query object