Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Grouping Mongoid Objects by Day

After much playing around in the console, I came up with this method to group activerecord-like (Mongoid) objects by the day on which they occured. I'm not sure this is the best way to accomplish this, but it works. Does anyone have a better suggestion, or is this a good way to do it?

#events is an array of activerecord-like objects that include a time attribute
events.map{ |event|
  # convert events array into an array of hashes with the day of the month and the event
  { :number => event.time.day, :event => event }
}.reduce({}){ |memo,day|
  # convert this into a hash with arrays of events keyed by their day or occurrance
  ( memo[day[:number]] ||= [] ) << day[:event]
  memo
}

=>  {
      29 => [e1, e2],
      28 => [e3, e4, e5],
      27 => [e6, e7],
      ...
    }

Thanks!

like image 921
Adam Avatar asked Mar 30 '11 05:03

Adam


People also ask

How can you group by a particular value in MongoDB?

We can group by single as well as multiple field from the collection, we can use $group operator in MongoDB to group fields from the collection and returns the new document as result. We are using $avg, $sum, $max, $min, $push, $last, $first and $addToSet operator with group by in MongoDB.

What is accumulator in MongoDB?

Accumulators are operators that maintain their state (e.g. totals, maximums, minimums, and related data) as documents progress through the pipeline. Use the $accumulator operator to execute your own JavaScript functions to implement behavior not supported by the MongoDB Query Language.

What is $$ root?

$$ROOT. The $$ROOT variable contains the source documents for the group. If you'd like to just pass them through unmodified, you can do this by $pushing $$ROOT into the output from the group.


1 Answers

After more thought and some help from Forrst, I came up with this:

events.inject({}) do |memo,event|
  ( memo[event.time.day] ||= [] ) << event
  memo
end

Apparently Rails monkeypatches Enumerable with a #group_by method that works like this:

events.group_by { |event| event.time.day }
like image 173
Adam Avatar answered Sep 23 '22 16:09

Adam