PHP で MongoDB をファイル ストレージとして使用する

Syed Hassan Sabeeh Kazmi 2023年6月20日
PHP で MongoDB をファイル ストレージとして使用する

大きなファイル用のスケーラブルなストレージを作成する場合、MongoDB とその GridFS (MongoDB クエリ言語 - MQL で記述) は、市場で最高のファイル ストレージ ソリューションの 1つです。 このチュートリアルでは、MongoDB を PHP のファイル ストレージとして使用する方法を学習します。

これにより、files コレクションの任意の部分に対するクエリのプロセスが容易になり、必要なデータをワーキング セットにロードすることで、他のクエリの場合と同じプロセスになります (ワーキング セットは、データのセットまたはロードされたデータを表します)。 最適なパフォーマンスを向上または維持するために、特定の時間枠内で MongoDB によって必要とされます。 さらに、RAM にページングすることにより、クエリ (データ/ファイルの保存、転送、操作) を行います。

その読み取りパフォーマンスは、RAM から直接小さなファイルに対して優れている場合もあれば、大きなファイルに対して優れている場合もあるため、さまざまです。 ほとんどのコンピューターには 600 GB 以上の RAM がなく、単一の mongod インスタンスで単一ファイルの 600 GB 以上のパーティションを簡単に処理できるため、これが予想されます。

ここで考慮すべき重要なことは、チャンクのデフォルトまたは平均サイズが 256KB であることです。これにより、600GB のファイル コレクションに対して膨大な量のドキュメントが作成されます。 ただし、ほとんどのドライバーでこの設定を操作できます。 GridFS は、他のコレクションと同様に、デフォルトのロック (データベース レベル 2.2+ またはグローバル レベル 2.2 より前) を使用します。

データベース レベル 2.2+ とグローバル レベル 2.2 より前のレベルは互いに干渉します。詳細を理解することで、作成中のドキュメントを一貫して読むことができます。

ドライバーが実装されているサーバーは、GridFS について何も認識していないことを意味し、サーバー側で GridFS データの特別な解決策はありません。 PHP プロジェクトで MongoDB を使用して GridFS を実装する方法を学習します。シナリオの詳細、トラフィック、同時書き込み/読み取りの数、およびその他の多くに基づいて競合が発生する可能性があるため、読み取り/読み取りのロックが発生する可能性があります。 場合によっては書き込み操作。

MongoDB の GridFS をファイル ストレージとして使用する

サイズが増加するファイル (BSON ファイルの 16MB のデフォルト制限を超える) には、より堅牢なストレージ システムが必要です。GridFS は、ファイルをチャンクに分割して、各チャンクを個別のファイル/ドキュメントとして保存/処理するため、大きなファイルを処理できます。 ファイルを単一のドキュメントとして保存する代わりに。 デフォルトのチャンク サイズは 255KB で、それらを 1つのコレクションに格納し、ファイル メタデータを別のコレクションに格納します。

システムレベルのファイルシステムは大きなファイルを処理できないため、MongoDB データベースに格納する方が効率的です。 GridFS は、ドキュメント全体をメモリにロードすることなく、大きなファイルの一部から情報にアクセスするための完璧なソリューションであり、ディレクトリ内のデータ/ストレージの制限を増やすためのパフォーマンス最適化ソリューションです。

さらに、ドキュメント、ファイル、およびメタデータの同期を支援し、地理的に分散されたレプリカ セット (複数の mongod インスタンスへのデータ分散) を使用する場合にファイルとそのメタデータを効率的かつ自動的に分散するために、多くのシステムにデータをデプロイします。 GridFS は、MongoDB ドライバーまたはmongofilesコマンドライン ツールの使用を含む 2つの方法で、プログラマーがデータを保存および配布するのを容易にします。

chunks コレクションと files コレクションを含む、GridFS が扱うコレクションには 2つのタイプがあります。 さらに、fs という名前のバックの fs.chunks による chunks コレクションと fs.files による files コレクションを表します。

/*
prerequisites

i) MongoDB 3.0 or higher
ii) PHP Driver

[Remember| install both on the same server]

This example will store a >1GB video on a MongoDB server.

the source code `mkdir src` must be stored in a directory so create one
to create a successful connection and understanding between your files and storage, create a settings file
your new directory will contain a `Settings.php` file with the following PHP contents:
*/

<?php
    # Remember| PHP 7.0 allows you to have one `define` using an array
    define("USERNAME_MONGODB", "[your_username]");
    define("PASSWORD_MONGODB", "[your_password]");
    define("DATABASE_MONGODB", "[your_databaseName]");
    define("SERVERIP_MONGODB", "[your_serverIP or your_hostname]");

    // the following script will enable file storage so you can store a file
    require_once(__DIR__ . '/Settings.php');

    if (!isset($argv[1]))
    {
        die("Please mention/pass the filepath to the file you want to store in MongoDB Server.");
    }

    $storage_filepath = $argv[1];

    if (!file_exists($storage_filepath) || is_dir($storage_filepath))
    {
        die("Invalid! Please, re-check your filepath.");
    }


    function mongo_Connect($your_username, $your_password, $your_database, $your_host_serverIP)
    {
        $con_MongoDB = new Mongo("mongodb://{$your_username}:{$your_password}@{$your_host_serverIP}"); // Connect to Mongo Server
        $con_database = $con_MongoDB -> selectDB($your_database); // Connect to Database
        return $con_database;
    }

    $con_database = mongo_Connect(
        USERNAME_MONGODB,
        PASSWORD_MONGODB,
        DATABASE_MONGODB,
        SERVERIP_MONGODB
    );

    $grid_FS = $con_database -> getGridFS();

    # you can stick any metadata here, e.g., upload the owner's ID, date of execution, etc.
    $add_metadata = array("date" => new MongoDate());
    $storage_filepath = $storage_filepath;
    $grid_FS -> storeFile($storage_filepath, array("metadata" => $add_metadata));

    // You can execute the script using the php `StoreFile.php` "filename.com.avi"
    // list files with the file size
    require_once(__DIR__ . '/Settings.php');

    function _mongoConnect($your_username, $your_password, $your_database, $your_host_serverIP)
    {
        $con_MongoDB = new Mongo("mongodb://{$your_username}:{$your_password}@{$your_host_serverIP}"); // Connect to Mongo Server
        $con_database = $con_MongoDB -> selectDB($your_database); // Connect to Database
        return $con_database;
    }

    $con_database = _mongoConnect(
        USERNAME_MONGODB,
        PASSWORD_MONGODB,
        DATABASE_MONGODB,
        SERVERIP_MONGODB
    );

    $grid_FS = $con_database -> getGridFS();

    # Loop over the files and output their names and file sizes
    $storage_files = $grid_FS -> find();

    while (($your_file = $storage_files -> getNext()) != null)
    {
        print $your_file -> getFilename() . "\t" . $your_file -> getSize() . PHP_EOL;
    }

    // retrieve files
    require_once(__DIR__ . '/Settings.php');

    if (!isset($argv[1]))
    {
        die("Please mention/pass the filepath to the file you want to store in MongoDB Server.");
    }

    $storage_filepath = $argv[1];

    if (!file_exists($storage_filepath) || is_dir($storage_filepath))
    {
        die("Invalid! Please, re-check your filepath.");
    }

    function mongoConnect($your_username, $your_password, $your_database, $your_host_serverIP)
    {
        $con_MongoDB = new Mongo("mongodb://{$your_username}:{$your_password}@{$your_host_serverIP}"); // Connect to Mongo Server
        $con_database = $con_MongoDB -> selectDB($your_database); // Connect to Database
        return $con_database;
    }

    $con_database = mongoConnect(
        USERNAME_MONGODB,
        PASSWORD_MONGODB,
        DATABASE_MONGODB,
        SERVERIP_MONGODB
    );

    $grid_FS = $con_database -> getGridFS();

    # in the following code, you can search for the filepath passed in as the first argument
    $search_fileParams = array("filename" => $storage_filepath);

    if (false)
    {
        # If you used absolute paths when storing files, then you could use the following to download a folder's contents.
        $folder = '/path/to/folder';

        # Refer to https://secure.php.net/manual/en/class.mongoregex.php
        $file_get_filename = new MongoRegex("/^$folder");

        $search_fileParams = array(
            'filename' => $file_get_filename
        );
    }

    # Alternatively, use findOne($search_fileParams) if you expect only one file with the provided name.
    $storage_files = $grid_FS -> find($search_fileParams);

    while (($your_file = $storage_files -> getNext()) != null)
    {
        # Use a random string in case there is a file with the same name in the current directory.
        $random_string = substr(str_shuffle(MD5(microtime())), 0, 10);
        $outputFile_path = __DIR__ . '/' . $random_string . "_" . basename($your_file -> getFilename());
        $your_file -> write($outputFile_path);
        print "Retrieved: " . $outputFile_path . PHP_EOL;
    }

    // use the script like
    // php RetrieveFiles.php "my_filename.mp4"
?>

出力:

Retrieved: my_filename.mp4

CLI ツールではなく (StoreFile() メソッドを使用するのではなく) PHP Web サイトを開発している場合は、StoreUpload() メソッドを使用します。 相対パスまたはフル パスを使用してファイルをシステムに保存します。MongoDB に保存されるファイル名は、/path/to/file.mp4 などのフル パスとファイル名を渡すと、渡された正確な文字列になります。 同じになります。

同じファイルでスクリプトを複数回呼び出しても失敗しないことに注意してください。 ただし、これを行うと、同じファイルを複数回保存する貴重なストレージ リソースが浪費される可能性があります。 PHP コード例は、MongoDB を PHP Web サイトまたはプロジェクトのデフォルト ストレージとして使用する方法を示しています。

Hadoop とその HDFS は MongoDB の優れた代替手段ですが、非常に複雑です。 ただし、MongoDB と比較して Map/Reduce ジョブをサポートしています。 最も重要なことは、GridFS の実装がドライバー自体のクライアント側であるため (特別な読み込みやファイルのコンテキストの理解なしで)、GridFS が最高のオプションであるということです。

MongoDB とその GridFS はドライバーで実装されており、仕様はさまざまです。ドライバーを使用すると、files コレクションからドキュメントのコレクションをクエリでき、プログラマーが後で単一のクエリで chunks コレクションからファイル自体を提供できるようになるためです。 . files コレクションとそれに続く chunks コレクションを作業セットに簡単にロードできます。

Syed Hassan Sabeeh Kazmi avatar Syed Hassan Sabeeh Kazmi avatar

Hassan is a Software Engineer with a well-developed set of programming skills. He uses his knowledge and writing capabilities to produce interesting-to-read technical articles.

GitHub