Module: CommandSearch::Mongoer

Defined in:
lib/command_search/backends/mongoer.rb

Class Method Summary collapse

Class Method Details

.build_command(node) ⇒ Object



19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/command_search/backends/mongoer.rb', line 19

def build_command(node)
  (field_node, search_node) = node[:value]
  key = field_node[:value]
  val = search_node[:value]
  search_type = search_node[:type]
  search_type = Boolean if search_type == :existence && val == true
  if search_type == Boolean
    # These queries can return true for empty arrays.
    val = [
      { key => { '$exists' => true } },
      { key => { '$ne' => !val } }
    ]
    key = '$and'
  elsif search_type == :existence
    val = { '$exists' => false }
  elsif search_type == Time
    return [{ CommandSearchNilTime: true }, { CommandSearchNilTime: false }] unless val
    return [
      { key => { '$gte' => val[0] } },
      { key => { '$lt' => val[1] } }
    ]
  end
  { key => val }
end

.build_compare(node, cmd_fields) ⇒ Object



44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/command_search/backends/mongoer.rb', line 44

def build_compare(node, cmd_fields)
  op_map = { '<' => '$lt', '>' => '$gt', '<=' => '$lte', '>=' => '$gte' }
  op = op_map[node[:nest_op]]
  key = node[:value][0][:value]
  val = node[:value][1][:value]
  if val.class == String && cmd_fields[val.to_sym]
    val = '$' + val
    key = '$' + key
    val = [key, val]
    key = '$expr'
  end
  { key => { op => val } }
end

.build_query(ast, fields, cmd_fields) ⇒ Object



81
82
83
84
85
86
# File 'lib/command_search/backends/mongoer.rb', line 81

def build_query(ast, fields, cmd_fields)
  build_searches!(ast, fields, cmd_fields)
  return {} if ast == []
  return ast.first if ast.count == 1
  { '$and' => ast }
end

.build_search(node, fields, cmd_fields) ⇒ Object



5
6
7
8
9
10
11
12
13
14
15
16
17
# File 'lib/command_search/backends/mongoer.rb', line 5

def build_search(node, fields, cmd_fields)
  val = node[:value]
  forms = fields.map do |field|
    type = cmd_fields[field.to_sym]
    if type == Numeric
      { field => node[:number_value] }
    else
      { field => val }
    end
  end
  return forms if forms.count < 2
  { '$or' => forms }
end

.build_searches!(ast, fields, cmd_fields) ⇒ Object



58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/command_search/backends/mongoer.rb', line 58

def build_searches!(ast, fields, cmd_fields)
  mongo_types = { paren: '$and', pipe: '$or', minus: '$nor' }
  ast.map! do |node|
    type = node[:nest_type]
    if type == :colon
      build_command(node)
    elsif type == :compare
      build_compare(node, cmd_fields)
    elsif key = mongo_types[type]
      build_searches!(node[:value], fields, cmd_fields)
      val = node[:value]
      if key == '$nor' && val.count > 1
        next { key => [{ '$and' => val }] }
      end
      val.map! { |x| x['$or'] || x }.flatten! unless key == '$and'
      { key => val }
    else
      build_search(node, fields, cmd_fields)
    end
  end
  ast.flatten!
end