Module: CommandSearch::Mongoer

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

Class Method Summary collapse

Class Method Details

.build_command(node) ⇒ Object



5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# File 'lib/command_search/backends/mongoer.rb', line 5

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) ⇒ Object



30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/command_search/backends/mongoer.rb', line 30

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

.build_query(ast) ⇒ Object



65
66
67
68
69
70
# File 'lib/command_search/backends/mongoer.rb', line 65

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

.build_searches!(ast) ⇒ Object



44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/command_search/backends/mongoer.rb', line 44

def build_searches!(ast)
  mongo_types = { and: '$and', or: '$or', not: '$nor' }
  ast.map! do |node|
    type = node[:type]
    if type == :colon
      build_command(node)
    elsif type == :compare
      build_compare(node)
    elsif key = mongo_types[type]
      build_searches!(node[:value])
      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 }
    end
  end
  ast.flatten!
end