MongoDB 儲存 13 位元組毫秒級時間戳(如 1347349162159)超出 32 位元整數範圍(最大 2147483647),必須以 64 位元整數 NumberLong 儲存。
// ❌ 字串查詢(資料為 NumberLong 時無匹配)
$query = ['log.stamp' => ['$gte' => '1347346800000', '$lt' => '1347350400000']];
// ❌ 純 PHP 整數(32 位元系統溢位,64 位元系統雖正確但非最佳實踐)
$query = ['log.stamp' => ['$gte' => 1347346800000, '$lt' => 1347350400000]];
// ✅ 明確指定 64 位元整數型別
$start = 1347346800000;
$end = 1347350400000;
$query = [
'log.stamp' => [
'$gte' => new MongoInt64($start),
'$lt' => new MongoInt64($end),
]
];
$cursor = $collection->find($query);
關鍵點: PHP MongoDB 驅動預設將數值視為 32 位元或浮點數,跨平台行為不一。MongoInt64 確保序列化為 BSON Int64 型別,與資料庫 NumberLong 精確匹配。
| PHP 類別 | BSON 型別 | 適用場景 |
|---|---|---|
MongoInt32 | Int32 | 32 位元整數 |
MongoInt64 | Int64 | 64 位元整數(時間戳、大數字 ID) |
MongoId | ObjectId | _id 主鍵 |
MongoDate | DateTime | 日期時間(UTC 毫秒) |
MongoRegex | Regex | 正則查詢 |
MongoCode | Code | JavaScript 代碼(MapReduce、$where) |
大數據量 MapReduce 易觸發游標超時(預設 10 分鐘),需在 command() 額外參數指定 timeout。
$map = new MongoCode('
function() {
var prop_id = this.log.cstparam.proId;
var key = this.log.site + prop_id;
emit(key, {channel: this.log.site, prop_id: prop_id, count: 1});
}
');
$reduce = new MongoCode('
function(key, emits) {
var total = 0;
for (var i in emits) total += emits[i].count;
return {channel: emits[0].channel, prop_id: emits[0].prop_id, count: total};
}
');
$query = [
'log.stamp' => [
'$gte' => new MongoInt64($timeRange['start']),
'$lt' => new MongoInt64($timeRange['end']),
]
];
// 關鍵:第二個參數傳入 timeout(毫秒)
$command = [
'mapreduce' => $collectionName,
'map' => $map,
'reduce' => $reduce,
'out' => $tmpResultCollection,
'query' => $query,
];
// timeout=0 表示無限等待,或設定具體毫秒數如 3600000 (1小時)
$options = ['timeout' => self::MONGO_CURSOR_TIMEOUT]; // 定義常數 MONGO_CURSOR_TIMEOUT = 0
$db->command($command, $options);
PHP MongoDB 擴充模組已歷經三代:
ext-mongo (舊版,已停維護) → 使用 MongoInt64、MongoCodeext-mongodb (新版核心驅動) + mongodb/mongodb (官方函式庫) → 使用 MongoDB\BSON\Int64、MongoDB\BSON\Javascriptuse MongoDB\BSON\Int64;
use MongoDB\BSON\Javascript;
$query = [
'log.stamp' => [
'$gte' => new Int64($start),
'$lt' => new Int64($end),
]
];
$map = new Javascript('function() { ... }');
$reduce = new Javascript('function(key, emits) { ... }');
$manager->executeCommand($dbName, new \MongoDB\Driver\Command([
'mapreduce' => $collName,
'map' => $map,
'reduce' => $reduce,
'out' => $outColl,
'query' => $query,
'maxTimeMS' => 3600000, // 新版用 maxTimeMS 替代 timeout
]));
MongoInt64/Int64 封裝new MongoDate($timestamp/1000) 自動轉 UTC 毫秒,支援原生日期查詢運算子log.stamp 欄位必須建立索引 db.coll.createIndex({'log.stamp': 1})mongodb/mongodb 函式庫,相容 PHP 7/8、支援現代 BSON 型別