我很难在 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>'
如何使此输出成为书籍投票的预期结果?