1

我有一个 Receipe 模型,我在提要中显示所有食谱。“Mac & Cheese”的那个提要中可能有 5 个实例。我想将它们组合在一起,并在提要中的“Mac & Cheese”旁边显示计数。我得到的那部分。我要显示的文档中有更多与食谱相关的信息,例如谁创建了它以及何时创建的。当我运行 Map/Reduce 时,我只是取回配方名称,然后计数,如何访问组中的最后一个文档以显示 user_id 和 created_at 以及其他文档属性?

class Recipe
  include Mongoid::Document
  include Mongoid::Timestamps
  include MongoidVote::Voteable
  include Tire::Model::Search
  include Tire::Model::Callbacks

  field :name
  field :slug

  belongs_to :user, :inverse_of => :recipes

  def self.grouped
    map = %Q{
      function () {
        emit(this.name, {count: 1});
      }
    }
    reduce = %Q{
      function(key, values) {
        var result = {count: 0};
        values.forEach(function(value) {
          result.count += value.count;
        });
        return result;
      }
    }
    self.all.
      map_reduce(map, reduce).out(inline: true)
  end
end

从控制台,一切都按预期工作。

recipes = Recipe.grouped
recipes.each do |r|
  puts r
end

{"_id"=>"Mac & Cheese", "value"=>{"count"=>3.0}}
{"_id"=>"Spaghetti and Meatballs", "value"=>{"count"=>1.0}}
{"_id"=>"Egg Sandwich", "value"=>{"count"=>2.0}}

我将如何访问每个配方的完整文档和关系以显示用户名、配方名称、配方计数?我是否需要遍历 Recipe.grouped 的结果并根据其名称重新查询完整的食谱文档,还是有其他方法可以走?

谢谢!

4

1 回答 1

2

如何访问组中的最后一个文档以显示 user_id 和 created_at 以及其他文档属性?

如果您只想要user_id所有具有相同名称的配方中的最后一个,您可以user_id在 mapper 中发出并在 reducer 中捕获它。

映射器:

function () {
  emit(this.name, {count: 1, user_id: this.user_id});
}

减速器:

function(key, values) {
  var result = {count: 0, user_id: null};
  values.forEach(function(value) {
    result.count += value.count;
    result.user_id = value.user_id; // we only care about the last one.
  });
  return result;
}

在您的情况下,最好使用2.2 中引入的聚合框架。对于大多数聚合操作,聚合管道提供了更好的性能和更一致的接口。该$group操作将满足您的所有需求。您可以使用$last来获取user_id$sum获取配方计数。

在 mongo shell 中,它看起来像:

db.recipes.aggregate(
    { $group : {
        _id : "$name",
        count : { $sum : 1 },
        user_id : { $last : "$user_id" }
    }}
);

如果你想要所有的 user_id,$push这就是你所需要的。

根据这个问题,Moped 支持聚合框架。 https://github.com/mongoid/moped/issues/49

我将如何访问每个配方的完整文档和关系以显示用户名、配方名称、配方计数?

由于 MongoDB 和 Mongoid 支持$in条件为 的批量查询find(),一旦你拥有了所有的 user_id,那只是一个额外的查询。

在您的情况下,似乎只需要用户名,username在配方文档中进行非规范化是保存额外查询的好主意。可以user_id在聚合框架中像上面一样检索它。

于 2013-09-18T15:46:48.293 回答