謎の技術研究部ホームタグ謎の技術研究部とはTop›プログラミング›Node.js2020-05-18【Node.js】巨大なJSONファイルを項目ごとに読み込むJSONStreamを使うReadStreamはバイト単位、Readlineは1行ごとだが、JSONStreamはJSONの項目で抽出して順番に読み込むライブラリ。こちらの使い方を説明するJSONStreamの必要性csvなどの1行ごとに区切って保存できるデータ形式であれば巨大ファイルであってもNode.jsのReadlineにより1行ごと順番に処理が可能である。JSON形式の巨大なファイルを取り扱おうとした場合、行では意味を成さないためNode.jsの標準ライブラリでは取り扱いが難しい(巨大なファイルを一括で読み込まねばならない)そこで使ってみたいと考えたのがJSONStreamこれを使えば巨大なJSONファイルも意味を成す塊に分けて順番にロードできる。},]}JSONの場合は入れ子構造によりどんどん複雑になっていく。特定の1個を取り出すなら簡単かもしれないが、この例のなかからrowsの配列に入っているオブジェクトのdocだけに絞って一つづつ取り出すのは難しい。そこでJSONStreamはJSONPathという概念を使って取り出していく。JSONPathとは例えばSQLのようにクエリを発行してそれに一致するデータを纏めて取り出す方法。JSONPathの構文については次が公式のようだ。上の例でいくとrows.*.docというJSONPathを発行すると次のデータが帰ってくる。2}これはJavaScriptで見れば次に一致する。data.rows){console.log(d.doc)}//rowsを1件づつ読み込み、さらにその中のdocだけを抽出している普通にオブジェクトのメンバ変数にアクセスするときの.だと思えばそこにワイルドカードなどが使えるようになっている印象だ。思ったよりわかりやすい。ここまで書いてはみたが残念ながら私はJSONPathに関して明るくない。今回はこれを説明するための記事ではないのである程度は他のサイトに譲りたい。興味があれば調べてみて欲しい。JSONStreamの使い方では実際に使っていく。}]あえて一番上の階層が配列になっている形式にした。以前作成した5秒足データに形状を似せている。必要なライブラリをインポート※公式にはevent-streamのライブラリを合わせて使っているが、使用しなくてもある程度できるようなのでここでは使用しないこととした。//ファイルを読み込むため用意するのはこれだけだ。次にファイルをfsで読み込んで.pipeでJSONStreamにつないでやる。.pipe(JSONStream.parse('$*'))pipeは入力から直接出力につなぐ時に使うもの。読んだファイルをそのまま別のファイルに出力したり標準出力process.stdout(普通のPCなら≒console.log)などに繋ぐといった利用法が挙げられる。JSONStreamはこの出力として振る舞っている。createReadStreamはStreamオブジェクトと呼ばれるものを返す。これをstreamという箱に格納した。JSONStream.parseここでparseが現れた。このメソッドがJSONPathを渡してデータを抽出するというコードだ。ここでは$*がJSONPathとして渡っている。$は一番上の要素(ルート)を指し*はワイルドカードなので、親の配列に格納されているデータを1個づつ全てにヒットする、といった感じだろうか。ちなみに$.*では何もヒットしない。.の次に入る文字列はキーを指す?データを1個づつ受け取るここがメインの処理。}}).onこれは先日話したevent-drivenの概念。データの読み込みが1個発生するごとにdataというイベントが発生しデータ1個分が引数に格納されてくる。先程streamを格納しておいたのはこのイベントを受取るため。単純にconsole.logで表示している。データのNoが3になった場合読み込みを中断するpauseメソッドを試している。これはJSONStreamではなくStreamオブジェクトの機能。}1行ごとに1回の処理に分けて実行。3回処理が実行されている。上で解説したpauseが機能するため4件目以降のデータは正しく止められている。上ではdata.valueとなっているが、これはサンプルデータの中にあるvalueではない。}どうやら親切なことにヒットしたデータをvalueに格納し、キー番号を付与してくれるようだ。不思議なことに冒頭の例「rows.*.doc」ではvalueとkeyに別れずデータがそのまま中に入ってくる。このあたりは配列に対して付与されるのか、$(一番親の要素)を使った時に付与されるのか詳しく調べていないのであしからず。全部合わせてもたったこれだけのコードだが、覚えることは多い。}})おまけ:書き込み書き込みにも使えるようだが詳しく調べていない。streamを生成するコードはJSONStream.stringifyを使うようだがなんと公式もここは詳細な実例を挙げておらず理解できなかった。どちらにせよNode.jsは「データの途中に挿入する形での書き込み」はワンランク上のプログラミング実装が必要であるため使うとしても一番うしろに追記するような使い方ぐらいだろう。さいごに今回はJSONStreamの特別なコードは殆ど使っていないが他にも複数のメソッドがある。興味があれば公式も参照してほしい(それほど多くない印象)とはいえこのライブラリはJSONPathが使えるかどうかがほぼ全てといっても過言ではないのでまずはそちらから覚えていったほうが良さそうだ。相変わらずこの手のコアなライブラリは日本語の情報が少ないためこの記事が少しでも役に立てたら幸いである。仮想トイレプログラミングや仮想通貨のシステムトレードに関する情報を発信中。どんな情報を流しても詰まらないトイレ。謎の技術研究部とはプライバシーポリシーホーム(自動スクロールなし)ご意見、お問い合わせ。