MongoDB
 sql >> Database >  >> NoSQL >> MongoDB

Come scorrere correttamente un file json di grandi dimensioni

Ti consigliamo di utilizzare un parser di streaming. Questi estraggono solo piccole porzioni del tuo file in memoria alla volta.

Sono disponibili in un paio di versioni diverse:parser push simili a SAX e parser pull. Modelli di lettori XML:parser pull SAX e XML fornisce una panoramica della differenza.

Spingi analizzatore

Questo è un rapido esempio di utilizzo di salsify/json-streaming-parser.

Man mano che scorre il file, terremo traccia di summonerId , championId , e stato. È tutto basato su eventi:non ottieni un accesso casuale con un parser sequenziale, quindi devi tenere traccia delle cose da solo. Ogni volta un totalSessionsPlayed viene visualizzato echeggerà l'summonerId , ID campione e totalSessionsPlayed .

data.json

Questo è un file json accoppiato a scopo dimostrativo.

[
    {
        "_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
            }
        }
    }
]

Esempio:

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;
}

Uscita:

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

Tira analizzatore

Questo sta usando un parser che ho scritto di recente, pcrov/jsonreader (richiede PHP 7.)

Stesso data.json di cui sopra.

Esempio:

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();

Uscita:

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