日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

MongoDB中关于64位整型存储解决方案

發布時間:2025/3/8 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 MongoDB中关于64位整型存储解决方案 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

為什么80%的碼農都做不了架構師?>>> ??

社區內一哥們@smcboy 提出關于php中操作MongoDB存儲整數問題,找到點資料花點時間翻譯過來,是個很好的學習方式。@紅薯 那篇討論我的修改回復,仍然沒有更新可惡啊~!!說實話我就是高一英語水平?為了這篇文章我算是絞盡腦汁,翻譯了大半天,累死我了??茖W精神可貴、可貴!!

在我當前項目中大量是MongoDB,正在從傳統RDBMS過度到key-value存儲。Facebook中用戶標識UserID使用64位Int數據類型存儲,杯具的是 MongoDB的PHP驅動只支持32位整型數據,導致UserID被截斷無法處理Facebook用戶信息。

MongoDB數據采用BSON(Binary JSON)文檔型存儲,BSON有兩種整型數據類型,1、32位有符號整型數據(INT); 2、64位有符號型整型數據(LONG)。由于PHP不支持大于8個字節整數,所以MongoDB PHP驅動只支持32位有符號整型數據存儲。然而這樣不是絕對的,在C類型 long 為64位平臺上,PHP仍然可以正常支持64位整型數據; 除了在Windowns上,其他平臺上C中long類型總是32位。


當PHP中整型存儲到MongoDB中,PHP驅動會采用最低兼容原則用32位進行轉換存儲到MongoDB文檔中。下面是測試案例(測試平臺為 64位):

$m = new Mongo(); $c = $m->selectCollection('test', 'inttest'); $c->remove(array()); //插入大于32位數據 $c->insert(array('number' => 1234567890123456));$r = $c->findOne(); echo $r['number'], "\n";

輸出:

int(1015724736) 二進制解析:
1234567890123456 = 1000110001011010101001111001000101010111010110000001015724736 = 111100100010101011101011000000
上面可以看出數據已被截斷,這顯然不是我想要的。為了解決這個問題,從PHP中存儲到MongoDB,我們可以采用原生的PHP整型數據。注意!不是去修改MongoDB相關驅動程序,而在PHP中配置一個簡單參數 mongo.native_long ,從而避免大量應用程序改動。當 mongo.native_long 參數開啟之后,我們可以看到如下不同的結果:

代碼:

ini_set('mongo.native_long', 1); $c->insert(array('number' => 1234567890123456));$r = $c->findOne(); var_dump($r['number']); 輸出:

int(1234567890123456)

在64位平臺中,PHP程序中配置mongo.native_long 允許使用完整64位整型存儲到MongoDB,本例中這種方式存儲到MongoDB中類型為BSON LONG, 如果未開啟此配置則類型為BSON INT類型。該配置對從MongoDB讀取數據到PHP中同樣有效。如果關閉該配置,當從MongoDB取出數據時PHP驅動會把 BSON LONG 類型轉換為PHP的double類型,造成精度損失。下面看個例子:

ini_set('mongo.native_long', 1); //開啟配置 $c->insert(array('number' => 12345678901234567));ini_set('mongo.native_long', 0); //關閉配置 $r = $c->findOne(); var_dump($r['number']); 輸出:

float(1.2345678901235E+16) 在32位平臺中 mongo.native_log 參數配置不起任何作用,仍然會以BSON INT 類型存儲。
然而當該配置開啟時從Mongo中取出 BSON LONG類型數據,MongoCursorException 會提示關于精度損失問題。
MongoCursorException: Can not natively represent the long 1234567890123456 on this platform
當該配置關閉時 BSON LONG 數據,為了兼容PHP會把 BSON INT 轉成float類型

盡管在64位平臺上可以使用該配置mongo.native_long達到支持64位整型的目的,但是并沒有提供32平臺上的解決方案,去防止BSON LONG 數據的精度丟失問題,僅僅不負責任的拋出一個精度丟失的異常信息( 詳情)。

工作中使用64位整位還是比較靠譜的,俺自己添加了兩個類庫 MongoInt32 和 MongoInt64,這兩個類簡單的封裝了用字符串表示數字。使用方式:?

$int32 = new MongoInt32("32091231"); $int64 = new MongoInt64("1234567980123456"); 使用該對象可以像正常使用插入、更新、查詢等操作
例如:
$m = new Mongo(); $c = $m->selectCollection('test', 'inttest'); $c->remove(array());$c->insert(array('int32' => new MongoInt32("1234567890"),'int64' => new MongoInt64("12345678901234567"), ));$r = $c->findOne(); var_dump($r['int32']); var_dump($r['int64']); 輸出結果:?

int(1234567890) float(1.2345678901235E+16) 可以看到對返回結果沒任何改變。BSON INT類型仍然是 int型,BSON LONG 類型變為 double類型。如果我啟用 mongo.native_long 配置,通過MongoInt64類庫轉換,在64位平臺上,PHP中獲取 BSON LONG 會返回正確int型,在32位平臺上MongoCursorException會拋出提示信息。

為了在32位平臺中,從MongoDB內取出 64位整型數據,需要配置另一個參數 mongo.long_as_object ,開啟后,BSON LONG取出后以一個MongoInt64對象返回。
案例:
$m = new Mongo(); $c = $m->selectCollection('test', 'inttest'); $c->remove(array());$c->insert(array('int64' => new MongoInt64("12345678901234567"), ));ini_set('mongo.long_as_object', 1); $r = $c->findOne(); var_dump($r['int64']); echo $r['int64'], "\n"; echo $r['int64']->value, "\n"; 輸出:

object(MongoInt64)#7 (1) {["value"]=>string(17) "12345678901234567" } 12345678901234567 12345678901234567 MongoInt32和MongoInt64 類基于對象的__toString()實現,所以返回的value值可以直接進行 echo,你只能獲取一個整型字符串,所以請意識到MongoDB是類型敏感的,不會用對待字符串的方式對待數字,數字就是數字。
案例(64位平臺):
ini_set('mongo.native_long', 1);$m = new Mongo(); $c = $m->selectCollection('test', 'inttest'); $c->remove(array());$nr = "12345678901234567"; $c->insert(array('int64' => new MongoInt64($nr)));$r = $c->findOne(array('int64' => $nr)); // $nr is a string here var_dump($r['int64']); $r = $c->findOne(array('int64' => (int) $nr)); var_dump($r['int64']); 輸出:

NULL int(12345678901234567)

下面列出關于不同的參數啟用狀態,整型轉換情況:

PHP to ?MongoDB (32位系統)

From PHP

Stored in Mongo

native_long=0

native_long=1

1234567

INT(1234567)

INT(1234567)

123456789012

FLOAT(123456789012)

FLOAT(123456789012)

MongoInt32("1234567")

INT(1234567)

INT(1234567)

MongoInt64("123456789012")

LONG(123456789012)

LONG(123456789012)

PHP to ?MongoDB (64位系統):

From PHP

Stored in Mongo

native_long=0

native_long=1

1234567

INT(1234567)

LONG(1234567)

123456789012

garbage

LONG(123456789012)

MongoInt32("1234567")

INT(1234567)

INT(1234567)

MongoInt64("123456789012")

LONG(123456789012)

LONG(123456789012)

Mongo to PHP (32位系統)

Stored in Mongo

Returned to PHP as

long_as_object=0

long_as_object=1

native_long=0

native_long=1

INT(1234567)

int(1234567)

int(1234567)

int(1234567)

LONG(123456789012)

float(123456789012)

MongoCursorException

MongoInt64("123456789012")

Mongo to PHP (64位系統):

Stored in Mongo

Returned to PHP as

long_as_object=0

long_as_object=1

native_long=0

native_long=1

INT(1234567)

int(1234567)

int(1234567)

int(1234567)

LONG(123456789012)

float(123456789012)

int(123456789012)

MongoInt64("123456789012")

總結:
綜上所述可以看到想獲得64位的支持還是很棘手的,如果你只需要在64為平臺上運行代碼,我們推薦使用 mongo.native_long=1 配置參數。當整數存儲到MongoDB,取出是仍然是整型數據,從而達到支持64位的目的。

如果你丫就是想要在32位平臺(包含Windows 64位上的PHP),你沒辦法使用得到可靠的整型數據,必須使用MongoInt64 類來實現。這也會帶來其他問題,如:你必須在初始化的時候處理字符串類型的數字。也要注意MongoDB Shell 將所有的數字作為float浮點型數據處理,這并不能代表64位整型數字,相反將作為浮點型數字。所有不要在shell模式下進行數據修改,這樣會導致類型轉換!!

案例:

$m = new Mongo(); $c = $m->selectCollection('test', 'inttest'); $c->remove(array());$c->insert(array('int64' => new MongoInt64("123456789012345678"))); MongoDB Shell模式下: $ mongo MongoDB shell version: 1.4.4 url: test connecting to: test type "help" for help > use test switched to db test > db.inttest.find() { "_id" : ObjectId("4c5ea6d59a14ce1319000000"), "int64" : { "floatApprox" : 123456789012345680, "top" : 28744523, "bottom" : 2788225870 } } 當我們通過驅動獲取支持64位數據,可以得到靠譜的結果: ini_set('mongo.long_as_object', 1); $r = $c->findOne(); var_dump($r['int64']); 輸出:

object(MongoInt64)#7 (1) {["value"]=>string(18) "123456789012345678" }

這個新函數方式將會在 ?mongo 1.0.9 release 版本中推出,可以通過PRCL ?pecl install mongo?獲取。

剩下的就靠命運了,祝你好運。

翻譯:OSC民工

原文鏈接:http://derickrethans.nl/64bit-ints-in-mongodb.html

轉載于:https://my.oschina.net/kisswu/blog/122338

總結

以上是生活随笔為你收集整理的MongoDB中关于64位整型存储解决方案的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。