首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP 操作 MongoDB 核心 CRUD 完整指南:連線、查詢、索引、聚合

     編輯:PHP 相關知識

前言

MongoDB 是文件導向的 NoSQL 資料庫,PHP 透過 mongodb 擴充套件(舊版 mongo 已棄用)進行操作。本文整理 連線參數、資料庫/集合選擇、CRUD 操作、查詢投影、索引建立、聚合管線、錯誤處理 等核心用法,並提供現代化的類別封裝範例。

環境需求


# 安裝 PHP MongoDB 擴充套件
pecl install mongodb

# composer 專案相依
composer require mongodb/mongodb

連線參數完整對照表

連線字串格式說明
mongodb://localhost:27017本機預設連線
mongodb://user:pass@localhost:27017帳密驗證
mongodb://user:pass@localhost:27017/dbname指定預設驗證資料庫
mongodb://host1:27017,host2:27017/?replicaSet=rs0副本集連線
mongodb+srv://cluster.mongodb.netAtlas SRV 記錄自動發現

核心 CRUD 實作範例

<?php
require 'vendor/autoload.php';

use MongoDB\Client;
use MongoDB\Collection;
use MongoDB\Database;

// 1. 建立連線
$client = new Client('mongodb://localhost:27017');

// 2. 選擇資料庫與集合
$db = $client->selectDatabase('myapp');           // 明確選擇
$coll = $db->selectCollection('users');           // 明確選擇

// ---------- Create ----------
// 插入單筆
$insertOne = $coll->insertOne([
    'name' => 'Alice',
    'email' => 'alice@example.com',
    'age' => 28,
    'tags' => ['vip', 'beta'],
    'created_at' => new MongoDB\BSON\UTCDateTime(), // 當前毫秒時間戳
]);
echo "Inserted ID: {$insertOne->getInsertedId()}\n";

// 批次插入
$insertMany = $coll->insertMany([
    ['name' => 'Bob', 'age' => 30],
    ['name' => 'Carol', 'age' => 25],
]);
echo "Inserted IDs: " . implode(', ', iterator_to_array($insertMany->getInsertedIds())) . "\n";

// ---------- Read ----------
// 查單筆(依 _id)
$user = $coll->findOne(['_id' => $insertOne->getInsertedId()]);
print_r($user);

// 條件查詢 + 投影 + 排序 + 分頁
$cursor = $coll->find(
    ['age' => ['$gte' => 25]],           // filter
    [
        'projection' => ['name' => 1, 'email' => 1, '_id' => 0], // 只回傳需欄位
        'sort' => ['age' => -1],         // 年齡降序
        'skip' => 0,                     // 分頁 offset
        'limit' => 10,                   // 分頁 limit
    ]
);
foreach ($cursor as $doc) {
    echo "{$doc['name']} ({$doc['email']})\n";
}

// 計算總數
$total = $coll->countDocuments(['age' => ['$gte' => 25]]);

// ---------- Update ----------
// 單筆更新($set 部分更新)
$updateOne = $coll->updateOne(
    ['email' => 'alice@example.com'],   // filter
    ['$set' => ['age' => 29, 'last_login' => new MongoDB\BSON\UTCDateTime()]]
);
echo "Matched: {$updateOne->getMatchedCount()}, Modified: {$updateOne->getModifiedCount()}\n";

// 多筆更新
$updateMany = $coll->updateMany(
    ['tags' => 'beta'],
    ['$set' => ['status' => 'active'], '$unset' => ['temp' => '']]
);

// ---------- Delete ----------
$deleteOne = $coll->deleteOne(['email' => 'bob@example.com']);
$deleteMany = $coll->deleteMany(['status' => 'inactive']);

// ---------- Index ----------
// 建立單欄位索引
$coll->createIndex(['email' => 1], ['unique' => true]);
// 複合索引
$coll->createIndex(['age' => 1, 'status' => 1]);
// 文字索引(全文搜尋)
$coll->createIndex(['name' => 'text', 'email' => 'text']);

// ---------- Aggregation ----------
$pipeline = [
    ['$match' => ['age' => ['$gte' => 18]]],
    ['$group' => ['_id' => '$status', 'count' => ['$sum' => 1], 'avgAge' => ['$avg' => '$age']]],
    ['$sort' => ['count' => -1]],
];
$results = $coll->aggregate($pipeline);
foreach ($results as $row) {
    print_r($row);
}

現代化封裝:Repository 模式

<?php
namespace App\Repository;

use MongoDB\Collection;
use MongoDB\Model\BSONDocument;

class UserRepository {
    private Collection $coll;

    public function __construct(Collection $coll) {
        $this->coll = $coll;
    }

    public function findByEmail(string $email): ?array {
        return $this->coll->findOne(['email' => $email]);
    }

    public function create(array $data): string {
        $data['created_at'] = new \MongoDB\BSON\UTCDateTime();
        $result = $this->coll->insertOne($data);
        return (string)$result->getInsertedId();
    }

    public function updateById(string $id, array $data): bool {
        $result = $this->coll->updateOne(
            ['_id' => new \MongoDB\BSON\ObjectId($id)],
            ['$set' => $data]
        );
        return $result->getModifiedCount() > 0;
    }

    public function paginate(array $filter, int $page, int $perPage): array {
        $cursor = $this->coll->find($filter, [
            'skip' => ($page - 1) * $perPage,
            'limit' => $perPage,
            'sort' => ['created_at' => -1],
        ]);
        return [
            'data' => iterator_to_array($cursor),
            'total' => $this->coll->countDocuments($filter),
            'page' => $page,
            'per_page' => $perPage,
        ];
    }
}

常見坑與解決方案

問題原因解法
MongoDB\BSON\ObjectId 無法直接 echo是物件非字串(string)$objectId 或 $objectId->__toString()
日期儲存為字串而非 BSON Date直接存 date('Y-m-d')用 new MongoDB\BSON\UTCDateTime() 或 new DateTime() 物件
大量資料 find() 記憶體爆炸游標預設在 PHP 端緩衝使用 batchSize() 或分批 limit/skip
聚合管線 $lookup 效能差缺乏索引或資料量過大建立外鍵欄位索引、考慮反正規化設計

結語

PHP 操作 MongoDB 的關鍵在於:使用官方 mongodb/mongodb 套件、善用 BSON 類型(ObjectId, UTCDateTime)、建立適當索引、聚合管線替代複雜查詢。建議專案引入 Repository 模式封裝集合操作,並配合 PHPUnit 測試資料存取層,確保 NoSQL 彈性結構下的資料一致性。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved