Module: Hightop::Mongoid

Defined in:
lib/hightop/mongoid.rb

Instance Method Summary collapse

Instance Method Details

#top(column, limit = nil, distinct: nil, min: nil, nil: nil) ⇒ 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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# File 'lib/hightop/mongoid.rb', line 5

def top(column, limit = nil, distinct: nil, min: nil, nil: nil)
  columns = column.is_a?(Array) ? column : [column]

  relation = all

  # terribly named option
  unless binding.local_variable_get(:nil)
    columns.each do |c|
      relation = relation.and(c.ne => nil)
    end
  end

  ids = {}
  columns.each_with_index do |c, i|
    ids["c#{i}"] = "$#{c}"
  end

  if distinct
    # group with distinct column first, then group without it
    # https://stackoverflow.com/questions/24761266/select-group-by-count-and-distinct-count-in-same-mongodb-query/24770233#24770233
    distinct_ids = ids.merge("c#{ids.size}" => "$#{distinct}")
    relation = relation.group(_id: distinct_ids, count: {"$sum" => 1})
    ids.each_key do |k|
      ids[k] = "$_id.#{k}"
    end
  end

  relation = relation.group(_id: ids, count: {"$sum" => 1})

  if min
    relation.pipeline.push("$match" => {"count" => {"$gte" => min}})
  end

  relation = relation.desc(:count)
  if limit
    relation = relation.limit(limit)
  end

  result = {}
  collection.aggregate(relation.pipeline).each do |doc|
    key = doc["_id"].values
    key = key[0] if key.size == 1
    result[key] = doc["count"]
  end
  result
end