Skip to content

Instantly share code, notes, and snippets.

@tuannguyen29
Last active December 6, 2019 01:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tuannguyen29/f503bb512e40de6a064aa5720063e05a to your computer and use it in GitHub Desktop.
Save tuannguyen29/f503bb512e40de6a064aa5720063e05a to your computer and use it in GitHub Desktop.
MongoDB PHP Library

MongoDB PHP Library

Install

PHP extension

Để sử dụng được MongoDB PHP Library cần cài đặt MongoDB PHP Driver. Chọn cách cài đặt phù hợp với flatform ở đây

  • Cài đặt cho wamp bằng cách tải PHP extension php_mongodb.dll.

  • Rồi thêm vào php.ini:

    [mongodb]
    extension=php_mongodb.dll
    

Thông qua composer

  • Cài đặt

    composer require mongodb/mongodb
    
  • Configure Autoloading

    require_once __DIR__ . "/vendor/autoload.php";
    

Setup cho Phalcon

Bind tới service container:

protected function initSharedCollectionManager()
{
    return new \MongoDB\Client();
}

Gọi tới collectionManager trong controller:

$collection = $this->collectionManager->mongo_color->users;

$document = $collection->findOne(['_id' => new ObjectId('5dddf77640730000ed00115e')]);

var_dump($document);
exit;

Để kết nối với database server, sử dụng một trong các cách sau:

<?php
$connection = new MongoClient(); // connects to localhost:27017
$connection = new MongoClient( "mongodb://example.com" ); // connect to a remote host (default port: 27017)
$connection = new MongoClient( "mongodb://example.com:65432" ); // connect to a remote host at a given port
?>

Insert Documents

Insert One Document

Method MongoDB\Collection::insertOne() insert một document duy nhất vào MongoDB và trả về một instance của MongoDB\InsertOneResult, mà bạn có thể sử dụng để truy cập ID của tài liệu được insert.

<?php

$collection = (new MongoDB\Client)->mongo_color->users;

$insertOneResult = $collection->insertOne([
    'username' => 'admin',
    'email'    => 'admin@example.com',
    'name'     => 'Admin User',
]);

printf("Inserted %d document(s)\n", $insertOneResult->getInsertedCount());

var_dump($insertOneResult->getInsertedId());

Output:

C:\wamp64\www\invo\app\controllers\IndexController.php:27:
object(MongoDB\BSON\ObjectId)[40]
  public 'oid' => string '5dddf4e740730000ed00115c' (length=24)

Output bao gồm ID của document được insert.

Nếu bạn thêm một giá trị _id khi insert document, MongoDB sẽ kiểm tra để đảm bảo rằng giá trị _id là duy nhất cho collection. Nếu giá trị _id không phải là duy nhất, thao tác insert không thành công do lỗi khóa trùng lặp.

Ví dụ sau đây insert một document trong khi chỉ định giá trị cho _id:

<?php

$collection = (new MongoDB\Client)->test->users;

$insertOneResult = $collection->insertOne(['_id' => 1, 'name' => 'Tuan Nguyen']);

printf("Inserted %d document(s)\n", $insertOneResult->getInsertedCount());

var_dump($insertOneResult->getInsertedId());
Inserted 1 document(s)
C:\wamp64\www\invo\app\controllers\IndexController.php:24:int 1

Lỗi khi trùng _id

E11000 duplicate key error collection: mongo_color.users index: _id_ dup key: { _id: 1 }

Insert Many Documents

Phương thức MongoDB\Collection::insertMany() cho phép bạn insert nhiều document trong một thao tác ghi và trả về một instance của MongoDB\insertManyResult, mà bạn có thể sử dụng để truy cập IDs của các document được insert.

<?php
$collection = (new MongoDB\Client)->mongo_color->users;

$insertManyResult = $collection->insertMany([
    [
        'username' => 'admin',
        'email'    => 'admin@example.com',
        'name'     => 'Admin User',
    ],
    [
        'username' => 'test',
        'email'    => 'test@example.com',
        'name'     => 'Test User',
    ],
]);

printf("Inserted %d document(s)\n", $insertManyResult->getInsertedCount());

var_dump($insertManyResult->getInsertedIds());

Output:

Inserted 2 document(s)
C:\wamp64\www\invo\app\controllers\IndexController.php:34:
array (size=2)
  0 => 
    object(MongoDB\BSON\ObjectId)[40]
      public 'oid' => string '5dddf77640730000ed00115d' (length=24)
  1 => 
    object(MongoDB\BSON\ObjectId)[33]
      public 'oid' => string '5dddf77640730000ed00115e' (length=24)

Query Documents

MongoDB PHP Library cung cấp các method MongoDB\Collection::findOne()MongoDB\Collection::find() để truy vấn document và method MongoDB\Collection::aggregate() để thực hiện các hoạt động tổng hợp.

Find One Document

MongoDB\Collection::findOne() trả về document đầu tiên khớp với điều kiện hoặc null nếu không có document nào khớp với điều kiện.

use MongoDB\BSON\ObjectId;

...
$collection = (new MongoDB\Client)->mongo_color->users;

$document = $collection->findOne(['_id' => new ObjectId('5dddf77640730000ed00115e')]);

var_dump($document);

exit;

Output:

object(MongoDB\Model\BSONDocument)[96]
  private 'storage' (ArrayObject) => 
    array (size=6)
      '_id' => 
        object(MongoDB\BSON\ObjectId)[95]
          public 'oid' => string '5dddf77640730000ed00115e' (length=24)
      'username' => string 'test' (length=4)
      'email' => string 'test@example.com' (length=16)
      'name' => string 'Test User' (length=9)
      'age' => float 27
      'status' => string 'Active' (length=6)

Note: Quy tắc so sánh của MongoDB là _id khớp với giá trị object của ObjectId, còn chuỗiObjectIds thì không thể so sánh trực tiếp.

Ví dụ:

['_id' => new ObjectId('5dddf77640730000ed00115e')]

Find Many Documents

MongoDB\Collection::find() trả về một object MongoDB\Driver\Cursor , có thể dùng vòng lặp để truy cập tới tất cả documents.

$collection = (new MongoDB\Client)->mongo_color->users;

$cursor = $collection->find(['status' => 'Active']);

foreach ($cursor as $document) {
    echo $document['_id'], "\n";
}

Output:

5ddcd69b609fe70e82cca0b4
5ddcd69b609fe70e82cca0b5
5ddcd69b609fe70e82cca0b6
5dddf77640730000ed00115e

Theo mặc định, các truy vấn trong MongoDB trả về tất cả các fields trong các documents. Để giới hạn số lượng dữ liệu mà MongoDB gửi đến các app, bạn có thể truyền một documents projection trong câu query.

MongoDB luôn có field _id theo mặc định trừ khi bạn loại trừ rõ ràng nó trong tài liệu projection.

$collection = (new MongoDB\Client)->mongo_color->users;

$cursor = $collection->find(
    [
        'status' => 'Active',
    ],
    [
        'projection' => [
            'name'     => 1,
            'age'      => 1,
            'username' => 1,
        ],
        'limit' => 2,
    ]
);

foreach ($cursor as $document) {
    echo '<pre>';
    print_r($document);
    echo '</pre>';
}

Output:

MongoDB\Model\BSONDocument Object
(
    [storage:ArrayObject:private] => Array
        (
            [_id] => MongoDB\BSON\ObjectId Object
                (
                    [oid] => 5ddcd69b609fe70e82cca0b4
                )

            [name] => MongoDB\Model\BSONDocument Object
                (
                    [storage:ArrayObject:private] => Array
                        (
                            [first] => Tuan 2
                            [last] => Nguyen
                        )

                )

            [age] => 35
        )

)
MongoDB\Model\BSONDocument Object
(
    [storage:ArrayObject:private] => Array
        (
            [_id] => MongoDB\BSON\ObjectId Object
                (
                    [oid] => 5ddcd69b609fe70e82cca0b5
                )

            [name] => MongoDB\Model\BSONDocument Object
                (
                    [storage:ArrayObject:private] => Array
                        (
                            [first] => Tuan Tuan
                            [last] => Nguyen
                        )

                )

            [age] => 36
        )

)

Limit, Sort, and Skip Options

Ngoài các tham chiếu trên, bạn có thể chỉ định các tùy chọn để Limit, Sort, and Skip các documents trong các truy vấn.

Ví dụ sau sử dụng các tùy chọn limitsort để lấy 5 users, sắp xếp age theo thứ tự giảm dần

$collection = (new MongoDB\Client)->mongo_color->users;

$cursor = $collection->find(
    [],
    [
        'limit' => 5,
        'sort' => ['age' => -1],
    ]
);

foreach ($cursor as $document) {
    printf("%s: %s\n", $document['username'], $document['age']);
}

Output:

admin2: 36
admin: 35
test: 27
admin123: 25
admin66: 24

Regular Expression

Các điều kiện để filter dữ liệu có thể sử dụng biểu thức chính quy thông qua class MongoDB\BSON\Regex

Ví dụ sau đây liệt kê các document trong collections users, với username bắt đầu là tuan:

$collection = (new MongoDB\Client)->mongo_color->users;

$cursor = $collection->find(
    [
        'username' => new MongoDB\BSON\Regex('^tuan', 'i'),
    ]
);

foreach ($cursor as $document) {
    printf("%s: %s\n", $document['username'], $document['age']);
}

Output:

tuan321: 21
tuan123: 23

Update Document

Update One Document

Sử dụng method MongoDB\Collection::updateOne() để update một document theo các điều kiện. MongoDB\Collection::updateOne() trả về một MongoDB\UpdateResult có thể sử dụng để truy cập số liệu thống kê về action update.

Các method update có hai tham số bắt buộc: điều kiện để truy vấn document và hành động nào sẽ được thực hiện.

Ví dụ: update name của user có age = 10 thành Bob Bob Bob

$collection = (new MongoDB\Client)->mongo_color->users;

$updateResult = $collection->updateOne(
    ['age' => '10'],
    ['$set' => ['name' => 'Bob Bob Bob']]
);

printf("Matched %d document(s)\n", $updateResult->getMatchedCount());
printf("Modified %d document(s)\n", $updateResult->getModifiedCount());

Output:

Matched 1 document(s)
Modified 1 document(s)

Trường hợp điều kiện update là đúng, nhưng không có sự thay đổi nào diễn ra, như đoạn code dưới đây thực hiện set một value đã tồn tại:

$collection = (new MongoDB\Client)->mongo_color->users;

$updateResult = $collection->updateOne(
    ['age' => '10'],
    ['$set' => ['name' => 'Bob Bob Bob']]
);

printf("Matched %d document(s)\n", $updateResult->getMatchedCount());
printf("Modified %d document(s)\n", $updateResult->getModifiedCount());

Output:

Matched 1 document(s)
Modified 0 document(s)

Update Many Documents

MongoDB\Collection::updateMany() có thể update một hoặc nhiều document theo các điều kiện query và trả về một MongoDB\UpdateResult có thể sử dụng để truy cập số liệu thống kê về action update.

$collection = (new MongoDB\Client)->mongo_color->users;

$updateResult = $collection->updateMany(
    ['age' => 10],
    ['$set' => ['name' => 'Bob Bob Bob']]
);

printf("Matched %d document(s)\n", $updateResult->getMatchedCount());
printf("Modified %d document(s)\n", $updateResult->getModifiedCount());

Output:

Matched 2 document(s)
Modified 2 document(s)

Replace Documents

Các thao tác replace tương tự như các update, nhưng thay vì update một tài liệu với các fields mới, hoặc các value mới cho field được chỉ định, thì thao tác replace sẽ replace toàn bộ document bằng một document mới, nhưng vẫn giữ nguyễn value gốc của field _id.

$collection = (new MongoDB\Client)->mongo_color->users;

$updateResult = $collection->replaceOne(
    ['name' => 'Bob Bob Bob'],
    ['name' => 'Bob Bob Bob', 'age' => 12]
);

printf("Matched %d document(s)\n", $updateResult->getMatchedCount());
printf("Modified %d document(s)\n", $updateResult->getModifiedCount());

Output:

Matched 1 document(s) 
Modified 1 document(s)

Tính tổng một column:

db.orders.aggregate([
    {
        "$match": {
            "field1": "a",
            "field2": "b"
        }
    },
    {
        "$group": {
           "_id": null,
           "total": { "$sum": "$price" }
        }
   }
]);

SQL tương đương:

SELECT SUM(price) AS total
FROM orders
WHERE field1 = 'a' AND field2 = 'b'

-- UPDATE -- With your document schema, to get the sum of payment_amount field with the conditions event_id is 342 AND ticket_type IN (84, 45, 365), use the following aggregation pipeline which starts with a $match pipeline stage that filters the documents with a given criteria and then groups those filtered documents using the $group operator to calculate the sum of the field payment_amount:

var pipeline = [
    {
        "$match": {
            "event_id": 342,
            "ticket_type": { "$in": [84, 45, 365] }
        }
    },
    {
         "$group": {
             "_id": null,
             "total": { "$sum": "$payment_amount" }
         }
    }
];
db.collection.aggregate(pipeline);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment