I have a collection called data. Each document looks something like this:
x: {"value"=>1358747699.6922424}, y: {"value"=>17.9}
Also, I have indexes on x.value and y.value. Using the built in mongoid aggregation .min, I wanted to get the minimum y value. I tried doing this:
data.min(:'y.value')
and it returns 16.2, which I know is not correct, it should be 14.4, which I can prove by:
data.map{|d| d['y']d['value']}.sort.first
returns 14.4
Or:
data.order_by([:'y.value', :asc]).limit(1).first['y']['value']
Also returns 14.4
So I can’t figure out why .min does not seem to be working correctly?
Short Answer
In your case, just ignore the
minfunction provided by Mongoid. Use the one you came up with instead:Explanation
I did some digging into how the Mongoid aggregations are actually implemented. Turns out they use a
map_reducethat runs the entire collection. [1]The query that you wrote should be much more efficient because it can use that index you built on
y.value. That means 1 index lookup versus the entire collection (not to mention it actually works…).Check the MongoDB profiler to ensure your indexes are actually being used. [2]
The Question you Actually Asked
As far as exactly why
minfails, I am at a loss. Without seeing your data, I can’t see any reason why the underlyingmap_reducewould fail. Maybe it has to do with the embedded field or maybethis.y.valueis not defined for some objects.Here’s an opportunity to give back to open source. Try posting to the Mongoid issues board. Be sure to crosslink if you do. I’d like to see the resolution for this.