先日、ちょっとしたキッカケで「あいまい検索」を作ってみようと思った。 アニメのタイトルで。 が、そもそもどうやって作るのかまったくわからない。 ただ、一応形態素解析とか N-gram とかは知っていたので、この辺を攻めればなんとかなるだろうと思ったのでちょっと考えた。 この時点で形態素解析を使ってしまうと使える範囲が限られてしまって楽しくなさそうなので、N-gram で行こうと最初に決めた。言語に依存しないし未知語に対しても強いし、アニメのタイトルのようなものに対しては相性が良さそうだから。 要するに似たものを出せばいいのだ。 例えば「らき☆すた」と「らきすた」は結構似ているが微妙に違う。Bigram を使うとすると、 らき☆すた: らき き☆ ☆す すた た らきすた: らき きす すた た のように分かれて、強調にした場所のような共通項が存在する。 特に後半の2つは連続でヒットしていて結構重要なデータと言えそうだ。 そういうのを見てスコアリングして順位を決めればいいのではないだろうか? と考えたので、実装してみた。 データは以下のような構造で保存した。 word コレクション 検索対象になる言葉の全文が入っているコレクション。 { "_id": "(MongoDBが適当に素敵な感じのを考えてくれる)", "word": "らき☆すた" } wordNgram コレクション 検索対象になる語句を N 文字に分割した状態のコレクション。 { "_id": "(MongoDBが適当に素敵な感じのを考えてくれる)", "w": "らき", "p": [ { "_id": "(wordコレクションでの「らき☆すた」の_id)", "pos": 0, //「らき☆すた」内での「らき」の出現位置 "len": 5 //「らき☆すた」の長さ } ] } こんな感じのものを沢