[SERVER-30729] NumberLong compare with Number Created: 18/Aug/17  Updated: 27/Oct/23  Resolved: 22/Aug/17

Status: Closed
Project: Core Server
Component/s: WiredTiger
Affects Version/s: 3.4.7
Fix Version/s: None

Type: Bug Priority: Major - P3
Reporter: tongzhilian Assignee: Mark Agarunov
Resolution: Works as Designed Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified
Environment:

http://downloads-distro.mongodb.org/repo/redhat/os/x86_64/RPMS/mongodb-org-server-2.6.1-1.x86_64.rpm
http://downloads-distro.mongodb.org/repo/redhat/os/x86_64/RPMS/mongodb-org-shell-2.6.1-1.x86_64.rpm


Issue Links:
Related
related to SERVER-24802 Database store a value different to t... Closed
Backwards Compatibility: Major Change
Operating System: ALL
Steps To Reproduce:

OnePiece:PRIMARY> db.test.save({_id: 123456789012345680, a: 1})
WriteResult({
        "nMatched" : 0,
        "nUpserted" : 1,
        "nModified" : 0,
        "_id" : 123456789012345680
})
OnePiece:PRIMARY> db.test.save({_id: 408457971232165500, a: 1})
WriteResult({
        "nMatched" : 0,
        "nUpserted" : 1,
        "nModified" : 0,
        "_id" : 408457971232165500
})
OnePiece:PRIMARY> db.test.find()
{ "_id" : 123456789012345680, "a" : 1 }
{ "_id" : 408457971232165500, "a" : 1 }
OnePiece:PRIMARY> db.test.find({_id: 123456789012345680})
{ "_id" : 123456789012345680, "a" : 1 }
OnePiece:PRIMARY> db.test.find({_id: NumberLong("123456789012345680")})
{ "_id" : 123456789012345680, "a" : 1 }
OnePiece:PRIMARY> db.test.find({_id: 408457971232165500})
{ "_id" : 408457971232165500, "a" : 1 }
OnePiece:PRIMARY> db.test.find({_id: NumberLong("408457971232165500")}) {color:#d04437} (Failed){color}
OnePiece:PRIMARY>

Participants:

 Description   

When compare number value with NumberLong, unexpect result got.

PS: The following step get expect result on mongod 2.4, failed both 3.2 && 3.4. (other version not tested)



 Comments   
Comment by Geert Bosch [ 22/Aug/17 ]

Old versions of MongoDB before 3.0 had an error on comparisons between floating point numbers and NumberLong for some values between 2 ** 53 and 2 ** 64. The NumberLong would be converted to a floating point number before comparison. This bug was fixed in SERVER-3719.

Comment by tongzhilian [ 22/Aug/17 ]

@Geert Bosch

IMO,
look like the comparison between number and NumberLong is changed from mongodb 3.0;

In mongodb 2.4, NumberLong is typecasted to number before comparison; and from mongodb 3.0, number is typecasted to NumberLong.

E.G.
in mongodb 2.4
> db.test.find({_id: 408457971232165500})

{ "_id" : 408457971232165500 }

> db.test.find({_id: 408457971232165504})

{ "_id" : 408457971232165500 }

> db.test.find({_id: NumberLong("408457971232165504")})

{ "_id" : 408457971232165500 }

> db.test.find({_id: NumberLong("408457971232165500")})

{ "_id" : 408457971232165500 }

in mongo 3.4
> db.test.save({_id: 408457971232165500, a: 1})
WriteResult(

{ "nMatched" : 0, "nUpserted" : 1, "nModified" : 0, "_id" : 408457971232165500 }

)
> db.test.find({_id:NumberLong("408457971232165504")})

{ "_id" : 408457971232165500, "a" : 1 }

> db.test.find({_id:NumberLong("408457971232165500")})
>

Comment by Geert Bosch [ 21/Aug/17 ]

The issue here is the conversion of the stored double precision number to a string. There actually is no double precision number 408457971232165500. Written in binary this number is 10110101011001000100101110001011000111110000100111001111100. This would require a mantissa of 57 bits, but the actual mantissa is only 53 bits for double precision numbers. The actual value of the stored double precision number is 408457971232165504, or 10110101011001000100101110001011000111110000100111010000000.

You can see this as well by typing `NumberLong(408457971232165500)`, which results in NumberLong("408457971232165504").
So, you can find your document by using this number:

> db.test.find({_id:NumberLong("408457971232165504")})
{ "_id" : 408457971232165500, "a" : 1 }

So, the data is stored correctly, but the double precision number is converted to text by the JavaScript interpreter using just 16 decimal digits, using trailing zeros . It appears that both the SpiderMonkey and V8 engines have this same behavior: only 16 significant digits are displayed as that is sufficient to convert back to the same double precision number. It would probably have been clearer if the number would have been output as 4.084579712321655e+17. Regardless, this is just an artifact of the JavaScript language and not something we can change.

Comment by Mark Agarunov [ 21/Aug/17 ]

Hello tong20078,

Thank you for the detailed report. I've been able to reproduce this behavior and we are currently investigating possible causes of this issue.

Thanks,
Mark

Comment by tongzhilian [ 18/Aug/17 ]

Environment is wrong. =>

https://repo.mongodb.org/yum/redhat/6Server/mongodb-org/3.4/x86_64/RPMS/mongodb-org-server-3.4.7-1.el6.x86_64.rpm
https://repo.mongodb.org/yum/redhat/6Server/mongodb-org/3.4/x86_64/RPMS/mongodb-org-shell-3.4.7-1.el6.x86_64.rpm

Generated at Thu Feb 08 04:24:49 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.