1

我很难在 Ruby 中使用 MongoDB 和 mongoid 创建 MapReduce 函数。我正在使用Ruby and MongoDB Web Development Guide,并且内容似乎不是为 Mongoid 编写的(即使它是在 Rails 3.2 之后编写的)。

这是一个示例 JSON 文档:

> db.books.find()
{ "_id" : ObjectId("50ceb8551d41c8ade7000041"), 
"author_id" : ObjectId("50ceb72c1d41c8ade700003d"), 
"category_ids" : [ ], "name" : "Great Expectations", 
"votes" : [     
  {     "username" : "Gautam",  "rating" : 9 },     
  {     "username" : "Tom",     "rating" : 3 },     
  {     "username" : "Dick",    "rating" : 7 } 
] 
}

无论如何,我在使用 mongoid MapReduce 时遇到了麻烦。我可以在 MongoDB 中很好地运行它:

> var reduce = function(key, values) {
  var result = {rating: 0};
  values.forEach(function(value) {
    result.rating += value.rating;
  });
  return result;
  };
> var map = function() {
  this.votes.forEach(function(x) {
    emit(x.username, {rating: x.rating});
  });
  };
> var results = db.books.mapReduce(map, reduce, {out: "mr_results"});
> results
{
    "result" : "mr_results",
    "timeMillis" : 28,
    "counts" : {
        "input" : 2,
        "emit" : 6,
        "reduce" : 3,
        "output" : 3
    },
    "ok" : 1,
}
> results.find()
{ "_id" : "Dick", "value" : { "rating" : 10 } }
{ "_id" : "Gautam", "value" : { "rating" : 15 } }
{ "_id" : "Tom", "value" : { "rating" : 10 } }

但是当我在 Rails 控制台中运行以下命令时,我得到了这个:

1.9.3-p327 :292 > map = "function() {
1.9.3-p327 :293"> this.votes.forEach(function(x) {
1.9.3-p327 :294"> emit(x.username, {x.rating});
1.9.3-p327 :295"> });
1.9.3-p327 :296"> }
1.9.3-p327 :297"> "
 => "function() {\nthis.votes.forEach(function(x) {\nemit(x.username, {x.rating});\n});\n}\n" 
1.9.3-p327 :298 > reduce = "function(key, values) {
1.9.3-p327 :299"> var result = {rating: 0};
1.9.3-p327 :300"> values.forEach(function(value) {
1.9.3-p327 :301"> result.rating += value.rating;
1.9.3-p327 :302"> });
1.9.3-p327 :303"> return result;
1.9.3-p327 :304"> }
1.9.3-p327 :305"> "
 => "function(key, values) {\nvar result = {rating: 0};\nvalues.forEach(function(value) {\nresult.rating += value.rating;\n});\nreturn result;\n}\n" 
1.9.3-p327 :306 > results = Book.where(votes: 1).map_reduce(map,reduce).out(inline: 1)
 => #<Mongoid::Contextual::MapReduce
  selector: {"votes"=>1}
  class:    Book
  map:      function() {
this.votes.forEach(function(x) {
emit(x.username, {x.rating});
});
}

  reduce:   function(key, values) {
var result = {rating: 0};
values.forEach(function(value) {
result.rating += value.rating;
});
return result;
}

  finalize: 
  out:      {:inline=>1}>

1.9.3-p327 :307 > results.find()
 => #<Enumerator: #<Mongoid::Contextual::MapReduce
  selector: {"votes"=>1}
  class:    Book
  map:      function() {
this.votes.forEach(function(x) {
emit(x.username, {x.rating});
});
}

  reduce:   function(key, values) {
var result = {rating: 0};
values.forEach(function(value) {
result.rating += value.rating;
});
return result;
}

  finalize: 
  out:      {:inline=>1}>
:find> 

或者,如果我将输出结果更改为“mr_results”,则会发生以下情况:

1.9.3-p327 :383 > results = Book.map_reduce(map,reduce).out("mr_results")
NoMethodError: undefined method `update_values' for "mr_results":String
        from /home/BSP/.rvm/gems/ruby-1.9.3-p327/gems/mongoid-3.0.14/lib/mongoid/contextual/map_reduce.rb:134:in `out'
        from (irb):383
        from /home/BSP/.rvm/gems/ruby-1.9.3-p327/gems/railties-3.2.9/lib/rails/commands/console.rb:47:in `start'
        from /home/BSP/.rvm/gems/ruby-1.9.3-p327/gems/railties-3.2.9/lib/rails/commands/console.rb:8:in `start'
        from /home/BSP/.rvm/gems/ruby-1.9.3-p327/gems/railties-3.2.9/lib/rails/commands.rb:41:in `<top (required)>'
        from script/rails:6:in `require'
        from script/rails:6:in `<main>'

如何使此输出成为书籍投票的预期结果?

4

1 回答 1

1

out函数需要一个哈希,而不是一个字符串:

results = Book.map_reduce(map,reduce).out(:replace => "mr_results")
于 2012-12-19T20:27:25.703 回答