未分類

@kaibaと申します。業務委託として手伝わせていただいております。 ​ Stampsでは導入店舗様が様々な条件で、来店してくれたアプリユーザにお知らせ、クーポン、アンケートなどを送ることができます。 サービスが育つとデータ量も増え、RDBMSでは厳しくなってきました。 今回はElasticsearchで高速化する話を書きます。 はじめに。Elasticsearchとは? StampsとElasticsearch 設計 join datatype どのように使うのか? プログラムからの呼び出し まとめ ​ はじめに。Elasticsearchとは? ​ ElasticsearchはElastic社がメンテしているOSSの全文検索エンジンです。ドキュメント指向のデータストアで、RDBが苦手とする部分一致検索や複雑な検索を高速に実行できます。Elastic cloud、Amazon Elasticsearch Serviceなどマネージドサービスにもなっていることも多く、環境構築と運用はすごく楽になりました。 ​ RDBと大きく異なるのは「ドキュメント」を扱うことです。ドキュメントとは雑にいうと1つのJSONです。Twitterを例に、ツイートを検索する例を考えると、以下のようなドキュメントを挿入することになります。 ​ { "id" : "6789", "full_text" : "こんにちは!", "created_at": "2019-01-01T04:00:00", "user" : { "id" : "1234", "name" : "kaiba", "screen_name" : "kaiba", } } ​ RDBではユーザの情報は別のテーブルに保持して正規化するのが一般的ですが、 Elasticsearchではこのように非正規化した形でドキュメントを保持します。 ​ 「screen nameが変更になったら不整合がおきないか」という不安が湧いてきます。 悩ましいところですが以下の案があります。 ​ screen name変更時にすべてのドキュメントを更新してやる サーバのコストや負荷が気になります screen nameを保持しないようにする screen nameでの検索を諦める screen nameからuser IDに変換して検索する join datatypeを使う(今回はこれを説明します) ​ StampsとElasticsearch ​ Stampsには様々な条件でアプリユーザにクーポン、お知らせ、アンケートなどをお届けできます。 例えば以下のようなケースです。​ 来店頻度によりお客様にクーポンを送る イベントに来ていただいたアプリユーザにアンケートをお送りし業務の改善に活かす 今月誕生日を迎えるアプリユーザに誕生日お祝いのクーポンをお送りする ​ 条件は複数組み合わせることができ、かなり複雑なクエリになっており、RDBだとどうしても速度と負荷の問題がありました。 ​ 設計 ​ Elasticsearchのドキュメントには検索に使用する項目だけを入れるのが一般的です。 今回検索に使用したい項目は大きく分けると以下になります。 ​ アプリユーザ(以後、単にユーザと呼びます) 来店情報 ユーザに対して来店情報は複数あり、どのようなindexにするか悩みました。 今回は、join datatypeを使用したのですが、以下も検討しました。 ​ ユーザに来店情報を配列で持たせる ユーザが来店すればするほどユーザのドキュメントが肥大化する 一部分だけ更新したいのに巨大なドキュメントを更新する必要がでてくるためリソースに不安がある 来店情報にユーザ情報を紐付ける ユーザの情報が更新されたときに大量のデータを同期する必要がある ユーザを探したいのに得られるのは来店情報になってしまい、複雑になる indexをユーザと来店情報に分割してしまう 2回Elasticsearchに対して検索することになる 「人気店のA店に1回以上来店した男性」のようなケースだと、「A店に1回以上来店した」ユーザが大量になるケースがあり、リソースに不安がある リクエストの実装が複雑になる ​ join datatype ​ Elasticsearchはjoin datatypeを 使用することでドキュメントに親子関係を持たせることができます。 ​ ただ、パフォーマンスに関して以下のような記載があり、ここが気になるところでした。 (僕なりの翻訳になります) ​ join datatypeはRDBのように使うべきではありません。 Elasticsearchでは非正規化してドキュメントを作ることで高いパフォーマンスが得られています。 ​ join datatypeが意味を成すのは1つのエンティティに対して大量のデータが含まれるケースです。 例えば製品と製品の注文です。この場合、製品を親、注文を子としてドキュメントにすることは適しています。   ​ 実際にstagingの数百万のレコードからドキュメントを構築してみたところ、十分なパフォーマンスが得られました! ​ どのように使うのか? ​ 先程のTwitterの例でjoin datatypeを構築してみます。 今回は「ユーザを検索する」のを目的に、ユーザとツイートが1対多の関係になるように構築します。 ​ 以下の形式でドキュメントを1つのindexに入れます。 ​ { "user" : { ...

こんにちは、22Inc.大薮です。 marketplace.visualstudio.com タイトルのままなのですが、VSCodeでRailsを書こうとすると、どうしても自分の欲しい操作感で使えるプラグインがなかったんすよね。 試しに作ってみたら意外にも簡単に実装できたので、自分でプラグインを作って公開するまでの流れを紹介します。 Simple Rails Navigator カンタン3Stepな手順です。 Step.1 準備 Step.2 実装 Step.3 公開 小並感 Step.1 準備 yoをインストールして、npm installします。 npmが入ってれば特に特別なことは何もしなくて大丈夫だと思います。 (試してないけど yarnでも大丈夫かな??) ➜ npm install -g yo npm WARN deprecated cross-spawn-async@2.2.5: cross-spawn no longer requires a build toolchain, use it instead /usr/local/bin/yo -> /usr/local/lib/node_modules/yo/lib/cli.js /usr/local/bin/yo-complete -> /usr/local/lib/node_modules/yo/lib/completion/index.js > spawn-sync@1.0.15 postinstall /usr/local/lib/node_modules/yo/node_modules/spawn-sync > node postinstall > yo@2.0.6 postinstall /usr/local/lib/node_modules/yo > yodoctor Yeoman Doctor Running sanity checks on your system ✔...