IBM Bluemix からも提供されている NoSQL 型 DBaaS の1つが Cloudant です:
2016071301


ベースとなる製品はオープンソースの Apache CouchDB です。私自身も以前は疑問に思っていたのですが、たまに聞かれる質問の1つに「Cloudant と Apache CouchDB は何が違うのか?」があります。

Cloudant は(ソフトウェア単体版も存在していますが) DBaaS としてクラウドで提供されているとか、 IBM の管理下で利用できる(サーバーインフラを自分が管理しなくてよい)とか、運用面での違いは比較的わかりやすいのですが、機能面での決定的な違いについてあまり目にする機会がありませんでした。

その違いの1つが今回紹介する「全文検索」機能です。一般的に NoSQL DB はスケーラビリティにすぐれた大容量データの保存に向くストレージシステムですが、SQL のようなクエリー言語が使えないこともあり、柔軟な検索はあまり得意ではありません。全文検索に関しては SQL DB であれば、
> select * from xxx where name like '%テスト%'

のような指定で「name にテストという文字を含むもの」が検索できます。パフォーマンス対策とか色々考慮すべき点はありますが、処理そのものは単純だし簡単・便利に実現できてしまいます。

一方で、一般的な NoSQL DB には全文検索を実現するためのこのような便利な機能がありません。Apache CouchDB でもインデックスを作成することで「完全一致検索」は実現できますが、「全文検索」はそうはいきません。Apache Lucene や ElasticSearch などの全文検索エンジンを使って NoSQL DB とは別に全文検索機能を実装し、併用して運用していくことになります。この方法はデータの一元管理が難しく、また DB と検索エンジンの整合性も併せて管理する必要が生じるため、比較的運用負荷の高い実現方法になってしまいます。

実はこの点で Cloudant は Apache CouchDB とは違います。Cloudant の検索機能には Apache Lucene が初めから含まれており、特に Lucene の存在を意識することなく全文検索インデックスが使えるようになっています。その使い方を紹介します。


まずは Cloudant のインスタンスを用意します。IBM Bluemix アカウントをお持ちであれば、サービスとして Cloudant を1インスタンス用意いただくのが一番簡単だと思います。IBM Bluemix アカウントがない場合は http://cloudant.com/ に直接サインアップしていただいても構いません。以下は前者の前提で紹介します。

作成した Cloudant の環境変数を参照して、Cloudant サービスを利用するための接続情報を確認します:
2016071301


サービス接続情報の JSON を確認し、credentials.url の値をメモしておきます(後で使います)。ここでは credentials.url の値が以下のようになっていると仮定して続きを紹介します:
{
  "credentials": {
    "username": "USERNAME",
    "password": "PASSWORD",
    "host": "USERNAME.cloudant.com",
    "port": 443,
    "url": "https://USERNAME:PASSWORD@USERNAME.cloudant.com"
  }
}


まずは Cloudant のダッシュボード画面にアクセスしてみます。まだ何も作業していなければ特にデータベースも作られてなく、データベース一覧は空の状態のはずです。ここでは今回の作業用に1つデータベースを追加することにします。画面右上の "Create Database" をクリックします:
2016071302


新規に作成するデータベースの名称を入力するよう求められるので適当に(以下の例では "mydb" と)入力して "Create" をクリックします:
2016071303


mydb データベースが新規に作成されました。が、(当たり前ですが)まだこのデータベースには何のドキュメントも登録されていません:
2016071304


検索作業用にいくつかのドキュメントを追加してみましょう。+印から "New Doc" を選択します:
2016071305


以下の様なドキュメント編集画面が表示されるはずです。ここに登録するドキュメントの内容を JSON 形式で入力していきます:
2016071306


今回は以下の様に "name" と "desc" という2つのフィールドを持つドキュメントを生成することにします("_id" は初めから入っている値をそのまま使います):
{
 "_id": "XXXXXXXX....XXX",
 "name": "Natural Language Classifier",
 "desc": "自然言語テキストを学習してカテゴリを分類する"
}

この状態でドキュメントを保存します。"Create Document" と書かれたボタンをクリックします:
2016071307


ドキュメントが保存されました。mydb データベースのドキュメント一覧からも参照できますが、指定した "name" や "desc" の値はこの画面からは確認できません。ドキュメントの内容を確認するには該当ドキュメントの右上の鉛筆マークをクリックします:
2016071308


"name" や "desc" 、そして追加された "_rev" の値なども確認することができます。正しく格納されているようです。一度 "<" 印をクリックして元の画面に戻ります:
2016071309


同様にしていくつかのドキュメントを追加していきましょう。上記の作業を繰り返して、とりあえず以下の3つのドキュメントが登録された状態にしておきます:
#name の値desc の値
1Natural Language Classifier自然言語テキストを学習してカテゴリを分類する
2Personality Insights入力されたテキストから性格を分析する
3Tradeoff Analytics優先順位を意識したトレードオフ判断を視覚化する


ではこのデータベースに全文検索の索引を追加して全文検索ができるようにします。mydb のメニュー画面から Design Documents 横の+印をクリックし、サブメニューから "New Search Index" を選択します:
2016071301


索引に関する情報を入力する画面に切り替わります。ここではデザイン ID ("_design/" と書かれた右)に "mydbdoc" と、インデックス名("Index name" と書かれた下)に "mydbsearch" とそれぞれ入力します:
2016071302


続けて下にスクロールし、Search Index function の中身を以下のように書き換えます:
function(doc){
 if ('name' in doc) {
  var search_this = [doc.name, doc.desc];
  index('default', search_this.join(' '));
  index('name', doc.name, {store: 'yes'});
  index('desc', doc.desc, {store: 'yes'});
 }
}
  ↑ "name" というフィールドを持つドキュメントに対して、
   "name" と "desc" の2フィールドを対象に検索インデックスを作成するようにしています。


最後に Type には "Japanese" を選択して、一番下の "Create Document and Build Index" をクリックします。これで検索索引が作成され、かつ索引付けが実行されて検索が可能になります:
2016071303


元の画面に戻ると "Build Indexes" 欄が追加されており、その中に作成したインデックス名称(mydbsearch)が表示されているはずです。これを選択すると検索のプレビューを確認することができるので、本当にこれだけで全文検索が可能になったのか試してみましょう:
2016071304


画面右の検索ボックスに「テキスト」と入力してみます(上記3ドキュメントと同じデータを登録していれば、3つのうちの2つのドキュメントが「テキスト」という文字列を含んでいるので、正しく検索できれば結果は2ドキュメントになることが予想されます):
2016071305


全文検索が実行され、画面のように2ドキュメントが検索結果にリストされました。正しく全文検索が実行されたことが確認できました:
2016071306


ちなみに、この検索処理を API で実行する場合は以下の URL に対して GET リクエストを実行することになります:
https://USERNAME:PASSWORD@USERNAME.cloudant.com/mydb/_design/mydbdoc/_search/mydbsearch?q=テキスト

指定する URL は以下の形になっています:
(上述の環境変数で取得した青字部分)/(DB名)/_design/(デザインID)/_search/(インデックス名)?q=(検索文字列)

試しにこの文字列をブラウザのアドレスバーに入力して実行すると、同じ2件の検索結果が得られるはずです:
2016071307


というわけで、Cloudant サービスには標準で Lucene ベースの全文検索エンジンが搭載されており、Apache CouchDB 同様に簡単に使うことができる上、NoSQL DB に苦手な全文検索が簡単に実現・実装することができる、という特徴を持っていることが確認できました。

(参考)
https://cloudant.com/product/cloudant-features/cloudant-search/