ruby的mongo驱动程序:`delete':无法将Symbol转换为String(TypeError)

时间:2013-04-14 05:36:03

标签: ruby mongodb

我收到了这个错误:

$ 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。

我做错了什么?

1 个答案:

答案 0 :(得分:1)

来自fine manual

  

- (收藏,哈希)map_reduce(map,reduce,opts = {})

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

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

因此它最终会使用Symbol参数调用String#delete,而不是String#delete期待的字符串,并且出现错误。

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

  

:outString) - 默认值: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{...}%q{...}引号:

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

当您使用嵌套引号时,这样更容易阅读并且噪音更少且容易出错。