Odd Map-Reduce failure with MongoDB and Mongoid

by Martin Westin in


I just want to document this for future reference. Google was very unhelpful so this is likely a rare error condition.

 

While making an innocent change to the query portion of a Mongoid map-reduce job it started throwing an exception. This exception: 

failed with error "ns doesn't exist"

Internet wizdom suggested a missing collection. One hit suggested a missing field as the cause. But my collection most decidedly was there. Other map-reduce jobs ran over it just fine. Other map-reduce jobs even ran fine using the exact same query "constraint".

Rails log showed all being well. Even the exception (displaying the map-reduce)  showed the expected query. Nothing indicated what was wrong.

Not to go too deep into the troubleshooting, the cause turned out to be a laziness an scope issue. The value for the query was out of scope when the lazy Mongoid processing got to it.

This would throw the exception.

Modelname.mongo_session.command(
mapreduce: Modelname.collection.name,
map: map_function,
reduce: reduce_function,
query: {"value.deep_value" => current_user.associated_thing.some_value},
out: {inline:1}
)

While this would not. 

deep_value = current_user.associated_thing.some_value
Modelname.mongo_session.command(
mapreduce: Modelname.collection.name,
map: map_function,
reduce: reduce_function,
query: {"value.deep_value" => deep_value},
out: {inline:1}
)

My guess is that it failed because the results were just put into an instance variable and not accessed until we were out in the view. Weird, yes. Reading Mongoid's and Moped's source might confirm or provide some other reason. From a practical standpoint though, assigning a local variable worked and I have better things to do right now :)