[SERVER-14935] Long number handling Created: 18/Aug/14 Updated: 10/Dec/14 Resolved: 18/Aug/14 |
|
| Status: | Closed |
| Project: | Core Server |
| Component/s: | Shell, Storage |
| Affects Version/s: | 2.6.3 |
| Fix Version/s: | None |
| Type: | Bug | Priority: | Major - P3 |
| Reporter: | Tudor Alexandru | Assignee: | Unassigned |
| Resolution: | Done | Votes: | 0 |
| Labels: | None | ||
| Remaining Estimate: | Not Specified | ||
| Time Spent: | Not Specified | ||
| Original Estimate: | Not Specified | ||
| Operating System: | ALL |
| Steps To Reproduce: | insert fairy large numbers in a collection, query for them. |
| Participants: |
| Description |
versus
Although i figured out that i was calling it wrong in the first case, i can't possibly imagine what is happening behind the scenes in the first case. How can it possibly work that way? The session field isn't indexed and we run a pretty big cluster. |
| Comments |
| Comment by Thomas Rueckstiess [ 18/Aug/14 ] | ||||||||||||||||||||
|
Hi Tudor, If a field’s value is a NumberLong (stored as 64-bit int) and you are searching using a double, the field's value will be cast to a double for comparison. This can cause precision loss on the cpp level (expected behavior). The conversion takes place in compareElementValues() in bsonelement.cpp. Separately, the behavior of Javascript == vs === in your example is also expected. You are comparing a number primitive to a NumberLong javascript object instance. That always shortcuts to false. Thomas | ||||||||||||||||||||
| Comment by Tudor Alexandru [ 18/Aug/14 ] | ||||||||||||||||||||
|
Even so, it shouldn't return more than one result with the .find() function. Is the mongodb server core also running on javascript? The data was saved properly, so in my mind the query should have returned 0 results. In your own words:
What is the exact internal representation of 100000000000068636 and how is it equal to the internal representation of NumberLong("xxx").. | ||||||||||||||||||||
| Comment by Thomas Rueckstiess [ 18/Aug/14 ] | ||||||||||||||||||||
|
Hi Tudor, MongoDB shell treats numeric values as floats by default, as described e.g. here. For convenience, it also has internal conversion between numeric types as can be seen in this example:
The document is returned even though the type was not the same. This includes NumberLong types as well.
Now it's easy to see why your query would return all these documents. When you entered the long number without specifying NumberLong, the shell interpreted it at floating point precision:
All documents within the precision of the number are returned as matches. To get the exact value back, as you discovered, you need to specify the query value as a NumberLong. As a side note, when querying for numeric values, you can also insist on a certain type with the $type operator, see this example:
I hope this explains the behavior you're seeing. I'll resolve the ticket as works as designed as I don't see an evidence for a bug here. Regards, |