俺流テキストデータベース #6 購入データの金額合計計算方法

2018/11/22

PHP テクノロジー プログラミング 特集

t f B! P L
プログラミングをやった後で、不具合が出てしまったものは、修正できるのですが、アルゴリズムを変更するというのは、非常にしんどいものがあります。 そもそも、不具合修正はゴールが見える作業になりますが、アルゴリズム変更は、変更により不具合が生まれる可能性もあり、手戻り感が半端ないので、仕事で行なってしまったプログラミングはアルゴリズム変更を躊躇してしまいがちですね。 でも、きっとやりかた失敗した〜という事は、多かれ少なかれ経験するものなので、そうならないために事前に経験を十分に積んでおかなければいけないという事もあるので、いきなり仕事に行き当たりばったりのプログラムを組む(設計する)のは、危険と考えてもいいかもしれません。 そんな僕も、今回書いているソースコードで使っているjqコマンドについて、深いところまで理解できていなかったんですが、本家のマニュアルを読んでいると、今回使っているjson-multi形式に普通に対応できるというオプションがあることを見つけました。 この処理のためにこれまでたくさんのパイプ繋ぎのコマンドを書いていたのですが、ほぼjqだけで行える事が判明したので、前回までの購入データ合計と合わせて、修正も同時に行っていきます。

ソースコード

<?php namespace textDatabase; class dataReadShell{ // price-sum public static function get_total_csv($filename){ unset($res); $cmd = array( " cat ". $filename .".csv ", " awk -F, 'BEGIN{total=0}{gsub(/&#44;/ , \"\" , $0);total += ($2 * $3)}END{print total}' " ); exec(join(" | " , $cmd) , $res); return $res[0]; } public static function get_total_json($filename){ unset($res); $cmd = array( "cat ". $filename .".json", " jq '[.[] | ({\"c\":.count , \"p\":.price | tostring | gsub(\",\";\"\") | tonumber}) | .c * .p] | add' " ); exec(join(" | " , $cmd) , $res); return join("-",$res); return $res[0]; } public static function get_total_json_multi($filename){ unset($res); $cmd = array( " cat ". $filename .".multi.json ", " jq -s '[.[] | ({\"c\":.count , \"p\":.price | tostring | gsub(\",\";\"\") | tonumber}) | .c * .p] | add' " ); exec(join(" | " , $cmd) , $res); return $res[0]; } }

実行結果

$ php read4.php [Total] csv : 72098 json : 72098 json-multi : 72098 finish ! 全ての処理が同じ結果を出しているので、正解している事がわかります。

解説

今までのプログラムよりも格段にシンプルになっている事がわかると思いますが、awsとjqにできる限りの作業を詰め込んで見ました。 なのでパイプつなぎの処理は極力無くしています。 catでデータを読み込むだけなので、シンプルawsとjqであれば、catすら書かなくてもいいんですが、phpとの受け渡しの利便性だけの為にこの処理にしています。

今回のポイント

csvはawkで処理していますが、前回はカラム3番目の合計値だけだったのを、カラム3(値段)にカラム2(個数)をかけて、それを最後に合計する仕様です。 単純計算であれば、このぐらいシンプルにするのが処理速度もかなり向上します。 json形式とjson-multi形式は、今回はほぼ同じ内容になってしまいました。 それはjqコマンドの"-s"オプションに気が付いたからですね。 これは、json形式になっていないデータの集まりを、配列jsonに変換して読み込んでくれるという便利オプションで、今回のようなロギングデータとしての改行区切りのjson形式で使うのに非常に当てはまるオプションでした。 これまで、たくさんのパイプで繋いで処理していたのがオプション1つであっさりできてしまって、jsonとjson-multiの違いも全く無くなってしまったので、今後は一本化できてしまう事になりました。 ※ただし、テキストデータベースでの扱いは基本的に分けたいので、このまま進めます。 そして、今回のjq処理では、カラムの文字列を数値に変換(不要文字を取り除く)処理や、それらの数値の必要に応じた四則演算が行われている点に注目です。 個別のレコード毎に処理して、最後に"add"する合計値の出し方もやってみたら勉強になりました。

次回予告

コマンドでロギングして集計処理をする大体の流れがわかってきたところで、果たしてテキストデータベースが本当に大容量データに対応できるのかを負荷計測も踏まえて検証してみたいと思います。

人気の投稿

このブログを検索

ごあいさつ

このWebサイトは、独自思考で我が道を行くユゲタの少し尖った思考のTechブログです。 毎日興味がどんどん切り替わるので、テーマはマルチになっています。 もしかしたらアイデアに困っている人の助けになるかもしれません。

ブログ アーカイブ