0

我收到了这个错误:

$ ruby mapreduce.rb
/usr/share/gems/gems/mongo-1.6.4/lib/mongo/collection.rb:618:in `delete': can't convert Symbol into String (TypeError)
    from /usr/share/gems/gems/mongo-1.6.4/lib/mongo/collection.rb:618:in `map_reduce'
    from mapreduce.rb:21:in `<main>'

使用以下代码:

require 'rubygems' 
  require 'mongo' 

  map = "function() { " + 
  "var keys = [];" + 
  "for ( item in this['kg'] ) { keys.push(item) }" + 
  "emit(keys.sort().join(';'), {count: 1})" + 
  "}" 
  reduce = "function(key, values) { " + 
  "var sum = 0; " + 
  "values.forEach(function(doc) { " + 
  " sum += doc.count; " + 
  "}); " + 
  "return {count: sum}; " + 
  "};" 
  out = "stats" 

  db = Mongo::Connection.new.db("test") 
  coll = db.collection("snps") 

  result = coll.map_reduce(map, reduce, out) 
  result.find.to_a.each do |r| 
puts ['{', r['_id'], ':', r['value']['count'].to_i, '}'].join(" ") 
  end 

使用以下 MongoDB 2.2.3。

我做错了什么?

4

1 回答 1

1

来自精美手册

-(集合,哈希)map_reduce(map,reduce,opts = {})

请注意,第三个参数map_reduce应该是一个选项哈希,但您传递的是一个字符串。如果您查看map_reduce源代码,您会看到:

def map_reduce(map, reduce, opts={})
  #...
  raw    = opts.delete(:raw)

所以它最终会使用 Symbol 参数而不是预期String#delete的 String调用,并且有你的错误。String#delete

您还可以在选项的文档中找到它:

:out( String) — 默认值:nil— 有效的输出类型。在 v1.7.6 之前的 MongoDB 版本中,此选项采用集合的名称作为输出结果。在 1.7.6 及更高版本中,此选项指定输出类型。有关可用的输出类型,请参阅核心文档。

所以想必你想说:

result = coll.map_reduce(map, reduce, :out => out)

不要这样做:

map = "function() { " + 
  "var keys = [];" + 
  "for ( item in this['kg'] ) { keys.push(item) }" + 
  "emit(keys.sort().join(';'), {count: 1})" + 
  "}"

请改用%Q{...}or%q{...}引号:

map = %q{function() {
  var keys = [];
  for ( item in this['kg'] ) { keys.push(item) }
  emit(keys.sort().join(';'), {count: 1})
}}

当您有嵌套引号时,这更容易阅读并且噪音更小且容易出错。

于 2013-04-14T05:56:56.267 回答