Как создать этот запрос mongoDB (mongomapper)

У меня есть некоторые документы с name: String и version: Integer.

Мне нужен список документов наивысшей версии на имя.

Поэтому я думаю, что мне нужно сделать эквивалент group by в sql, а затем having для версии max для каждого имени.

Я понятия не имею, с чего начать это с mongoDB. Если бы кто-нибудь мог сделать этот запрос для терминала mongo, это было бы отличным началом, но дополнительным бонусом было бы предоставление синтаксиса специально для MongoMapper.


person MarioDS    schedule 17.05.2013    source источник


Ответы (3)


Если вы используете Mongodb версии 2.2+, вы можете выполнить свой запрос, используя структуру агрегации с оператором группового конвейера.

Документация находится здесь: http://docs.mongodb.org/manual/reference/aggregation/ < / а>

MongoMapper не имеет помощника для фреймворка агрегации, но вы можете использовать драйвер Ruby напрямую (версия драйвера 1.7.0+ имеет агрегированный вспомогательный метод). Вам нужно будет получить экземпляр Mongo :: Collection и вызвать для него агрегатный метод. Например:

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

Надеюсь, это поможет!

person Emily S    schedule 03.06.2013
comment
Что ж, ваша идея хороша, но мне плохо, что это не совсем то, что мне нужно - мне нужен не только фактический самый высокий номер версии, мне нужен весь документ ... - person MarioDS; 04.06.2013
comment
В этом случае вы можете использовать оператор $ push, чтобы собрать все значения для определенного поля в такой массив: Model.collection.aggregate ([$ group = ›{_id =› $ name, max_version = ›{$ max = ›$ Version}, other_fields =› {$ push = ›$ other_field}}]) Или выполните запрос после агрегирования и найдите документ, соответствующий этой версии и имени. - person Emily S; 04.06.2013

Если вы хотите создать группу с помощью Mongo DB, проверьте Aggregation Framework, это точный инструмент для работы!

Здесь вы найдете эквивалент в Aggregation Framework для GROUP BY, ИМЕТЬ и многое другое.

person Simon    schedule 17.05.2013
comment
В этом случае проверьте, поддерживает ли он предшественника структуры агрегирования, Map Reduce - person Simon; 17.05.2013
comment
да, похоже, есть варианты для уменьшения карты определенными способами, но это довольно сложно, и вам нужно реализовать большую часть этого самостоятельно. Если это, к сожалению, единственное решение, я пока буду придерживаться хитрости, которую придумал, так как у меня нет времени, чтобы выяснить, как уменьшить карту. - person MarioDS; 17.05.2013

Благодаря @Simon я взглянул на Map Reduce с помощью MongoMapper. Я, вероятно, не идеален, но он делает то, что я хочу. Вот реализация:

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
person MarioDS    schedule 04.06.2013