【问题标题】:Mapreducing to count the occurrence of fields that may or may not existMapreducing 计算可能存在或不存在的字段的出现
【发布时间】:2011-09-06 11:11:56
【问题描述】:

这给了我一个错误 {"assertion"=>"map invoke failed: JS Error: ReferenceError: foo is not defined 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 

【问题讨论】:

    标签: javascript ruby-on-rails ruby mongodb mapreduce


    【解决方案1】:

    我已尝试重现您的问题。但是,仅出于练习问题,我编写了以下运行良好的代码。我只是希望这仍然有用。

    命令行:

    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
    

    【讨论】:

      【解决方案2】:

      JavaScript 对我来说看起来不错,但也许 MongoDB 正在添加额外的限制,从而导致奇怪的错误消息。我可以想到两件事您可以尝试:使用hasOwnProperty 来查看foobar 是否存在:

      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
      

      请注意,我已经收紧了这个逻辑以查看 foobar 是否存在,而不仅仅是检查它们的真实性。

      【讨论】:

      • 我最终还是回到了尝试:emit(this.user_id, {foo: this.foo, bar: this.bar}) 第一次没有用,但现在可以了吗?所以我想不需要所有额外的代码。不过还是谢谢!
      【解决方案3】:

      分配给哈希时需要将 foo 和 bar 放在引号中:

      hsh["foo"] = this.foo;  // or hsh.foo = this.foo
      

      您可以考虑将此问题标记为 javascript,因为 ruby​​ 部分很少。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-03-26
        • 1970-01-01
        • 2011-10-03
        • 2018-12-09
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多