Go の hashicorp/go-multierror 使ったら訳わからん挙動に遭遇してしまった
基本的な Go の挙動が理解できてないのかもしれないですが、なぜ以下のコードで (2) err != nil: true
となるのかが分かりません。
誰か教えて… (g()
がメソッドなのはなるべく元のコードと似せたせいです)
追記
KoRoN さんとりんだんさんに教えてもらいました。
型なしの nil はほぼ存在しないんです。で、型が異なる同士のnilは比較しちゃいけないではなくて、比較しても常に異なってしまうから実質役に立ちません。
— MURAOKA Taro (@kaoriya) 2018年4月1日
— ドッグ (@Linda_pp) 2018年4月1日
というわけで教えてもらった記事の最初に「Goのinterfaceの実体は参照と型情報のペア」と書いてありました。 Go 公式の FAQ にも書いてあります。 こっちのが私のコードより問題と解決策が一目で分かりやすかったので皆さんもハマる前にぜひ。
MongoDB で190万件あるコレクションに $regex で LIKE 検索する時にパフォーマンスの観点で気を付けること
150万以上ある Mongo のレコードに LIKE 検索したい時こうすると雲泥の差になった (1分以上かかってたのが 50ms 以下になった)。
— tyru (@_tyru_) 2018年3月22日
①インデックスを使う ($hint 指定しないと $regex の場合は使われないっぽい)
②パターンの頭に ^ を付ける
③パターンに .* を使わない
④パターンに () を使わない
控えめに150万件以上と言ったけど実際は190万件ぐらいだった。
以下の全てのクエリは 0 件を返す。
というか今見たら $and
使う必要はなかった。
// 89790ms db.getCollection('colName').find({$and: [{name: /(あああ)/}, {status: 1}]}) // 1361ms db.getCollection('colName').find({$and: [{name: /^(あああ)/}, {status: 1}]}).hint({name: 1}) // 4ms db.getCollection('colName').find({$and: [{name: /^あああ/}, {status: 1}]}).hint({name: 1}) // 107386ms db.getCollection('colName').find({$and: [{name: /^(あああ)/}, {status: 1}]}) // 86117ms db.getCollection('colName').find({$and: [{name: /^あああ/}, {status: 1}]})
/(あああ)/
よりヒントなしの /^(あああ)/
が遅いのが謎。
ちなみに文字列検索した時は普通にインデックスが効くっぽいのですぐ返ってくる。
// 15ms db.getCollection('colName').find({$and: [{name: "あああ"}, {status: 1}]})
公式ドキュメント
- case insensitive なパターンを使うこと
^
や\A
で始めること- 先頭からのマッチの長さをなるべく短くする
- 例えば
/^a/
,/^a.*/
,/^a.*$/
だったら/^a/
が一番速い - [私見] 安易に
.*
とか書かずにどうしても必要なら non-greedy match にするといいかも (.*?
)
- 例えば
あとドキュメントに書いてないけど冒頭の結果から分かるのは
()
を使わない
もですかね。
TODO
$explain した結果も貼る。
Puppeteer で楽天銀行の入出金明細を保存
以前楽天銀行でワンタイムパスワードを突破しつつ明細履歴を TSV ファイルに保存するスクリプトを書いた。 ワンタイムパスワードのメールを受け取って本文をパースするために IMAP にログインしてメールが来るまで待つ、みたいな事をしている。
前のは id:motemen さんのスクリプトを参考にさせてもらいながら書いたので Protractor + WebDriver 製だった。
ただ最近はなんやかんや (Headless Chrome + Chrome Debugging Procotol) で Chrome を GUI のない環境でも動かす事ができて、 さらにヘッドレス Chrome を操作する Puppeteer というライブラリもある。 しかもこれは Google 自身が開発しているのでサードパーティのライブラリよりも大分信頼できる。
Puppeteer はフラグ1つ変えるだけでヘッドレスで動作するかどうかを切り替える事ができるので、 開発中は非ヘッドレスでやりながら、うまくいったらヘッドレスにして Linux サーバで cron で動かすとかができてだいぶ便利 (のはず)。 ちなみに自分の環境は Windows 10 で元々 Chrome を入れてたので使わなかったけど、 Puppeteer 自体に Chrome をダウンロードしてくる機能とかもあるらしい。
ということで冒頭のスクリプトを Puppeteer で書き直してみた。 Node v8.10.0 で動作確認済みです。
Puppeteer の API
詳しくはこの辺を見てください。
スクリプトの解説
すみません、力尽きました。
すでに色んなブログとかで Puppeteer の解説されてるので省略。
あとでやるかも
楽天 e-NAVI (楽天カードの明細取得) とかもスクレイピングしたかったんだけど、そもそも e-NAVI は CSV で明細を取得できるのでログインしてそれをダウンロードすればええやん、 と思ったら CSV 取得を Fetch API でやろうとしてうまくいかなかった (HTML が返ってきてしまう)。 ちなみにダウンロードの URL はこれ。ログインしてれば CSV がダウンロードされるはず。
https://www.rakuten-card.co.jp/e-navi/members/statement/index.xhtml?downloadAsCsv=1
誰か pull request 送ってください。