sql >> データベース >  >> NoSQL >> MongoDB

大きなjsonファイルを適切に反復処理する方法

    ストリーミングパーサーを使用することをお勧めします。これらは、一度にファイルのごく一部のみをメモリにプルします。

    それらには、SAXのようなプッシュパーサーとプルパーサーの2つの異なるフレーバーがあります。 XMLリーダーモデル:SAXとXMLプルパーサー 違いの概要を説明します。

    プッシュパーサー

    これは、salsify/json-streaming-parserを使用した簡単な例です。

    ファイルをロールスルーするときに、summonerIdを追跡します。 、championId 、および状態。これはすべてイベントベースです。シーケンシャルパーサーではランダムアクセスが得られないため、自分で物事を追跡する必要があります。 totalSessionsPlayedのたびに summonerIdがエコーアウトします 、 championId 、および totalSessionsPlayed

    data.json

    これは、デモンストレーション用のペアダウンされたjsonファイルです。

    [
        {
            "_id": "53b29644aafd413977b23b7e",
            "summonerId": 24570940,
            "region": "euw",
            "stats": {
                "110": {
                    "totalSessionsPlayed": 3,
                    "totalSessionsLost": 2,
                    "totalSessionsWon": 1
                },
                "112": {
                    "totalSessionsPlayed": 45,
                    "totalSessionsLost": 2,
                    "totalSessionsWon": 1
                }
            }
        },
        {
            "_id": "asdfasdfasdf",
            "summonerId": 555555,
            "region": "euw",
            "stats": {
                "42": {
                    "totalSessionsPlayed": 65,
                    "totalSessionsLost": 2,
                    "totalSessionsWon": 1
                },
                "88": {
                    "totalSessionsPlayed": 99,
                    "totalSessionsLost": 2,
                    "totalSessionsWon": 1
                }
            }
        }
    ]
    

    例:

    class ListMatchUps extends JsonStreamingParser\Listener\IdleListener
    {
    
        private $key;
        private $summonerId;
        private $championId;
        private $inStats;
    
        public function start_document()
        {
            $this->key        = null;
            $this->summonerId = null;
            $this->championId = null;
            $this->inStats    = false;
        }
    
        public function start_object()
        {
            if ($this->key === 'stats') {
                $this->inStats = true;
            } else if ($this->inStats) {
                $this->championId = $this->key;
            }
        }
    
        public function end_object()
        {
            if ($this->championId !== null) {
                $this->championId = null;
            } else if ($this->inStats) {
                $this->inStats = false;
            } else {
                $this->summonerId = null;
            }
        }
    
        public function key($key)
        {
            $this->key = $key;
        }
    
        public function value($value)
        {
            switch ($this->key) {
                case 'summonerId':
                    $this->summonerId = $value;
                    break;
                case 'totalSessionsPlayed':
                    echo "{$this->summonerId},{$this->championId},$value\n";
                    break;
            }
        }
    }
    
    $stream = fopen('data.json', 'r');
    $listener = new ListMatchUps();
    try {
        $parser = new JsonStreamingParser_Parser($stream, $listener);
        $parser->parse();
    } catch (Exception $e) {
        fclose($stream);
        throw $e;
    }
    

    出力:

    24570940,110,3
    24570940,112,45
    555555,42,65
    555555,88,99
    

    プルパーサー

    これは、私が最近書いたパーサー、pcrov / jsonreader(PHP 7が必要)を使用しています。

    上記と同じdata.json。

    例:

    use pcrov\JsonReader\JsonReader;
    
    $reader = new JsonReader();
    $reader->open("data.json");
    
    while($reader->read("summonerId")) {
        $summonerId = $reader->value();
        $reader->next("stats");
        foreach($reader->value() as $championId => $stats) {
            echo "$summonerId, $championId, {$stats['totalSessionsPlayed']}\n";
        }
    }
    $reader->close();
    

    出力:

    24570940, 110, 3
    24570940, 112, 45
    555555, 42, 65
    555555, 88, 99
    



    1. MongoDBの監査ログを使用した事前のセキュリティ

    2. パンダを使用した大規模なデータワークフロー

    3. MongoDB $ atan2

    4. MongoDB:サブドキュメントフィールド値の個別のリストを取得するにはどうすればよいですか?