Question

I have certain documents with a name: String and a version: Integer.

What I need is a list of documents of the highest version per name.

So I think I need to do the equivalent of group by in sql and then a having for max version per name.

I have no idea where to start to do this with mongoDB. If anyone could make this query for the mongo terminal that would be a great start, but an added bonus would be to give the sytnax for MongoMapper specifically.

Was it helpful?

Solution 3

Thanks to @Simon I had a look at Map Reduce with MongoMapper. My take on it is probably not perfect, but it does what I want it to do. Here's the implementation:

class ChildTemplate
  ...
  key :name, String
  key :version, Integer, :default => 1

  ...

  private
  def self.map
    <<-JS
    function() {
      emit(this.name, this);
    }
    JS
  end

  private
  def self.reduce
    <<-JS
    function(key, values) {
      var res = values[0];
      for(var i=1; i<values.length; i++)
      {
        if(values[i].version > res.version)
        {
          res = values[i];
        }
      }
      return res;
    }           
end

def self.latest_versions(opts = {})
  results = []
  opts[:out] = "ct_latest_versions"
  ChildTemplate.collection.map_reduce(map, reduce, opts).find().each do |map_hash|
    results << map_hash["value"]
  end
  return results
end

OTHER TIPS

If you are on Mongodb version 2.2+, you can do your query by using the aggregation framework with the group pipeline operator.

The documentation is here: http://docs.mongodb.org/manual/reference/aggregation/

MongoMapper doesn't have a helper for the aggregation framework but you can use the Ruby driver directly (driver version 1.7.0+ has an aggregate helper method). You would have to get an instance of Mongo::Collection and call the aggregate method on it. For example:

Model.collection.aggregate(["$group" =>
    {"_id" => "$name",
     "max_version" => {"$max" => "$version"}}
   ])

I hope that helps!

If you want to do a group by with Mongo DB, check the Aggregation Framework, it is the exact tool for the job !

Here you'll find the equivalent in Aggregation Framework for GROUP BY, HAVING, and more.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top