这给了我一个错误{“断言”=>“地图调用失败:JS错误:ReferenceError:foo未定义nofile_b:4”。有什么想法吗?
class ObjResults
include Mongoid::Document
field :foo, :type => Boolean, :default => false
field :bar, :type => Boolean, :default => false
def self.stats_by_user_id user_id
map = <<-MAP
function() {
if (this.user_id == "#{user_id}") {
hsh = {}
if (this.foo) {
hsh["foo"] = this.foo
}
if (this.bar) {
hsh["bar"] = this.bar
}
emit(this.user_id, hsh);
}
}
MAP
答案 0 :(得分:1)
在分配哈希值时,您需要将foo和bar放在引号中:
hsh["foo"] = this.foo; // or hsh.foo = this.foo
您可以考虑将此问题标记为javascript,因为ruby部分很小。
答案 1 :(得分:0)
JavaScript看起来很好,但是MongoDB可能会添加额外的限制,导致奇怪的错误消息。我可以想到您可以尝试的两件事:使用hasOwnProperty
查看foo
和bar
是否存在:
map = <<-MAP
function() {
if (this.user_id == "#{user_id}") {
hsh = { };
if (this.hasOwnProperty('foo')) {
hsh["foo"] = this.foo;
}
if (this.hasOwnProperty('bar')) {
hsh["bar"] = this.bar;
}
emit(this.user_id, hsh);
}
}
MAP
或使用括号表示法访问this
的属性:
map = <<-MAP
function() {
if (this.user_id == "#{user_id}") {
hsh = { };
if (typeof this['foo'] != 'undefined') {
hsh["foo"] = this.foo;
}
if (typeof this['bar'] != 'undefined') {
hsh["bar"] = this.bar;
}
emit(this.user_id, hsh);
}
}
MAP
请注意,我已经收紧了这个中的逻辑,看看foo
和bar
是否存在,而不仅仅是检查它们的真实性。
答案 2 :(得分:0)
我试图重现你的问题。但是,就实践问题而言,我写下了运行良好的代码。我只是希望这仍然有用。
命令行:
2.0.0p0 :023 > Band.all.to_a.map(&:bar)
=> [false, false, true, false]
2.0.0p0 :024 > Band.all.to_a.map(&:foo)
=> [false, false, true, true]
2.0.0p0 :025 > Band.mar.to_a
=> [{"_id"=>"Apple", "value"=>{"likes"=>888.0, "hh"=>3.0}}, {"_id"=>"IBM", "value"=>{"likes"=>1431.0, "hh"=>0.0}}]
代码结构:
class Band
include Mongoid::Document
field :name, type: String
field :likes, type: Integer, default: 0
field :foo, type: Boolean, default: false
field :bar, type: Boolean, default: false
def self.mar
map = %Q{
function() {
hsh = {};
if(this.foo) {hsh.foo = this.foo}
if(this.bar) {hsh.bar = this.bar}
emit(this.name, { likes: this.likes, hh: hsh });
}
}
reduce = %Q{
function(key, values) {
var result = { likes: 0, hh: 0 };
values.forEach(function(value) {
result.likes += value.likes;
if(value.hh.foo) {result.hh += 1}
if(value.hh.bar) {result.hh += 1}
});
return result;
}
}
self.where(:likes.gt => 100).map_reduce(map, reduce).out(inline: true)
end
end