テックアカデミー第12回メンタリング:仕様変更w検索機能をRailsで実装する

2018年4月13日

現在作成中のオリジナルWEBサービス(ある店舗の口コミサイト)にて、概ね順調に開発が進んでいます。ところでここ2日ほど考え続けている事があるのですが、それが↓

店舗の検索部分の仕様を検討しています。

今回のテックアカデミー第12回メンタリング(講師とのビデオ通話)では、検索機能と仕様変更の相談をさせてもらいました。

もし自前のアプリを作成中で検索機能を付与しようとしてる人がいればこの記事が参考に‥なるわけないか(ヽ´ω`)

さて検索窓に入力してもらったキーワードを元に、2つの検索を行います。

①自前のデータベース内からあいまい検索して取得
②Yahoo地図APIに投げて候補を取得

②のYahooの方は検索はお任せなので問題ないけど、①のほうをどうしようか検討しているのです。

検索窓に何というキーワードが入力されるのか?

完全に予想でしかありませんが以下のようなキーワードを想定しました。

地名 新宿、名古屋、福岡、東京、札幌、etc..
地名+市区町村 新宿区、大阪市、高崎市、中央区
地名+ランチ 新宿 ランチ、名古屋 ランチ
地名+業種 新宿 レストラン、新宿 居酒屋
地名の業種 新宿のレストラン、個室がある居酒屋
地名+店舗名 新宿 デニーズ、サイゼリヤ 池袋、ココス 横浜
店舗名のみ デニーズ、吉野家、リッツ・カールトン
店舗名+駅 デニーズ 新宿駅、名駅 味噌カツ屋
地名まで含む店舗名 デニーズ 新宿店、魚民 日本橋店
店舗名のみ きこりのお家

検索ユーザーは様々な人がいます。PCで入力する人も居れば、スマホで入力、音声で入力する人もいるかもしれません。

また年齢や性別もバラバラです。普段から検索が慣れている若い人とは別で慣れてない人は検索が上手に出来ないかもしれません。

そんな背景を意識しながらどんなキーワードを入力してくるかを想定します。

また、現時点でデータベース内で扱っているのは

店舗名 name
住所 address
最寄り駅 moyorieki

のみです。

ここからユーザーが検索したキーワードを元に、こちらのDBに保存しているどの店舗を表示させてあげればよいか、どうやってヒットさせるかを調査しています。

最初は甘く考えていたのですが検討すればするほど難解な事がわかってきました。

検索を行うときの課題

まず2語の複合語のキーワード(例 「新宿 レストラン」)と入力された時にどうするか?

>SELECT * FROM SHOPS NAME WHERE ‘%新宿 レストラン%’;

これだと1件もヒットしません。

新宿 スペース レストラン なんていうお店も住所もDBにはありませんので。
ここでやりたいのは、「新宿」でかつ「レストラン」に該当するものを探す‥というのがミッションです。

だからまずは検索キーワードをスペースで分割しないといけません。

でも、これが「新宿のレストラン」で検索されたら、スペースが無いので分割できない。この時点でアウトです。

この課題の答えは検索窓を2つにするという事になりますが‥

検索窓が2つあるシステムってどうなの~?という話もあります。

[地名] × [店舗名 または ジャンル]

とかでしょうか。要検討。テックアカデミーの講師にも相談。

複合キーワードのどっちが地名なの?

取り敢えず「新宿 レストラン」で検索された時にシステムではスペースで分割し「新宿」と「レストラン」にわけます。

ところで、どちらが地名なのかシステム視点ではわかりません

データベースの中に日本全国の地名のみを格納したデータ(十万件とか?)を保持しておいて、検索されたキーワードで地名DBを照合して地名かどうかを判定すれば可能です。

でも問題があって、検索語が◯◯市とか◯◯駅だったら、「市」や「駅」を外した◯◯部分で検索しないといけません。

10万件の住所マスタをDBに保持しておく事も現実的なのだろうかと思います。

業種をDBに格納する仕様変更

現時点の店舗DBには「業種」を扱うコードが入っていません。例えば「レストラン」「居酒屋」「カフェ」「ビュッフェ」「ラーメン」「中華」といったものです。

これを扱うように仕様変更も検討中です。

というのも「新宿 レストラン」で検索された時に業種が無いから自前のDB中からはヒットできないからです。これはほぼやらなきゃいけない仕様変更になりそう。

どんな業種のパターンがあるのか整理しました。

和食、洋食、中華、イタリアン、フレンチ、アジア料理、バイキング、ラーメン、カレー、焼き肉、鍋、居酒屋、定食屋、オーガニック、カフェ、喫茶店、パン、スイーツ、バー、パブ、スナック、ファミレス、ファーストフード、パーティ、カラオケ、レストラン、ビュッフェ‥

このような感じでしょうか。検索ユーザーの心理を考えるともっと細分化されそうですね。そこまで思いを巡らしてアプリを作る事が親切なアプリ設計とも言えるでしょう。頑張りどころか。

店舗名だけで検索されたら

検索窓1個にして店舗名で検索されたときは普通にnameカラムからあいまい検索をすればいけそうだ。ただ入力された店舗名がミスってたり、カタカナが平仮名だったり、漢字がひらがなだったり、スペースが多かったりすると、それだけでヒットしなくなりそう。

Google様の検索だったら打ち間違いキーワードとかも拾ってくれるし。

そういうのやろうとしたらまず無理なので。

まずは店舗名なのか地名なのかを判定するための仕様を検討する必要があります。地名DBマスタを持つか検索窓を2個にするか。。

検索窓2個パターンなら
[地名] x [ 店舗名 または ジャンル ]
ぐらい店舗の方を幅広にすればいいかも。

店舗名を入力しやすく幅広に取ってあげようと思いました。

あーよみがなカラムも必要なのか?!!

あいまい(LIKE)検索の逆はできないか

通常の検索SQLだと、以下のような処理になりますよね。

DBに「新宿駅」「新宿区」「渋谷区」「渋谷駅」「品川区」「品川駅」と入ってて
検索語が「渋谷」だったら LIKE句でヒットする。

SELECT * FROM AREA_TABLE WHERE NAME LIKE ‘%渋谷%’

こんなSQL文を発行すれば「渋谷区」と「渋谷駅」がヒットするでしょう。

逆にこんなケースは検索できないのでしょうか。

DBに「新宿」「渋谷」「恵比寿」「品川」と入ってて
検索語が「新宿駅」だったときにヒットさせたい。

SELECT * FROM AREA_TABLE WHERE NAME LIKE ‘%新宿駅%’;

これだと1件もヒットしません。

こちら残念ながら逆LIKE文みたいなSQLは出来ないとのことでした。

ユーザーのキーワード履歴を保存する?

今まで考えてこなかったのですが、ユーザーが入力したキーワードはDBに保存しておくようにしよう。

じゃないとどんなワードで検索してきてるのか把握できない。ゆくゆくはこの検索語をためてより使いやすい検索機能にしたいと思っています。

検索窓は1個がベストだが、2個がよいか、3個が良いか。

[地名] x [店舗名] x [ジャンル]

検索窓3つはちょっとありえないけど、ユーザーの検索行為を制限するという意味ではシステム的には優しくなりますね。

検索窓が増えると保持するキーワードも増えてくる懸念があります。

テックアカデミーメンタリングの結果仕様変更した部分

色々と相談させてもらった結果、次のように変更して進めていく事にしました。

検索窓 → 現状の1窓から2窓に変更

[地名] x [店名 または ジャンル]

検索窓1つでユーザーの様々な検索パターンを予想して網羅するのは大変だし、それはGoogleの検索を作ることに近い話になってくるので。

また講師の方にRailsで頭の良い検索を自動で行ってくれるようなGemは無いか聞いてみたのですが、検索まわりは想定外の事が起こるので、Gemとか探すよりは自分で実装した方がよいとのアドバイスでした。

ショップテーブルに「ジャンル(業種)」カラムを追加

この実装はやらないといけないです。

Railsでカラム追加て以前失敗してるから慎重にやりたい。

キーワード履歴の保存はやらない

これは講師の方になるべくDBへの出し入れは数が増えると負荷がかかるのでやらないほうが良いとのアドバイス。

それよりもグーグルアナリティクスをサイトに仕込んで、アナリティクスツールを使えば検索キーワードを取れるはず、との事により。

画像のアップロード機能

以前も聞いたのですがRailsで作ったWEBアプリは普通のレンタルサーバーにアップロードして動くようにするのはかなり難しいんだそうです。それでHerokuという海外のサーバーを利用する事が推奨されています。

Railsのアプリには3つのモードがあります。それがテスト、デベロップメント、プロダクションの3つです。本番環境でリリースするにはプロダクションモードで動かすべきですが、それらを意識して設定をする必要があります。

しかしこのherokuだとプロダクションモードの設定やセキュリティやパフォーマンス等をお任せでやってもらえるという利点があり推奨されてる訳ですね。自分はまだ「海外」とか「英語」が嫌いなので出来れば日本のサーバーで運用したいと諦めていないのですが。

ところがこのherokuサーバーだと画像をアップロード出来ない(ためておけない)という課題がありまして、じゃぁどうするのという話です。

まだリサーチ段階ですが参考で以下のURLを教えてもらいました。

https://devcenter.heroku.com/articles/direct-to-s3-image-uploads-in-rails

https://elements.heroku.com/addons/cloudinary

Ruby好き非エンジニアブログ

画像アップロードのための施策です。まぁこれが正解というわけではなく参考になるかも?とのことで。

これから調べて自分のアプリに適用できるか確認して進めていきます。

仕様変更なんかよりすごくハードルが高いです(; ・`ω・´)

すでに今まで様々な試練(問題解決できない、調べ方がわからない、乗ってない、うまくいかない、エラーが消えない)があり、その都度Railsなんてやめようかな‥と思いながらも続けてきました。

今回もなんとか乗り越えたいと思います。しかしアラフォーやぞ(●`ε´●)

てことで皆さんもプログラミング頑張っていきましょう!