しばやん雑記

ASP.NET とメイドさんが大好きなフリーランスのプログラマーのブログ

Azure Search を使ってツイートログ検索を実装してみた

また Azure の新機能が色々と発表されましたが、個人的には Azure Search が特に気になったので使ってみることにしました。既に抱かれたい男 No.1 が触っているので、そっちも参照してください。

Azure Search ちょっとさわってみた « ブチザッキ

日本語周りの対応が個人的には気になったので、今回は自分のツイートログを Azure Search に突っ込んで検索するようなコードを書いて試しました。自然言語が満載なので、いい感じの確認が出来ると思います。

まだ公式には REST API しか公開されていないっぽいですが、RedDog.Search というライブラリがほぼ同時に公開されているので、これを使うことで比較的簡単に Azure Search の操作が行えました。

reddog-io/RedDog.Search · GitHub

とりあえずはプレビューポータルから Azure Search を作る必要があります。

f:id:shiba-yan:20140822202922p:plain

作成されるまでにちょっと時間がかかるかもしれませんので、その間にサンプルアプリケーションを作成しておきます。と言っても、NuGet で RedDog.Search をインストールすれば環境は整います。

Azure Search に限らず検索系のサービスはインデックスを作らないと検索を行えないので、まずはインデックスを作成します。

// API へのアクセスに必要な情報
var connection = ApiConnection.Create("shibayan", "KEY");

// インデックスへの操作を行う場合に使う
var client = new IndexManagementClient(connection);

// tweets という名前で id, status, createdOn を持つインデックスを作成
await client.CreateIndexAsync(new Index("tweets")
    .WithStringField("id", p => p.IsKey().IsRetrievable())
    .WithStringField("status", p => p.IsSearchable().IsRetrievable())
    .WithDateTimeField("createdOn", p => p.IsRetrievable().IsSortable())
);

RedDog.Search は Fluent Interface を採用しているので、わかりやすく設定できます。インデックスのフィールド指定で使っているラムダ式では以下の拡張メソッドでフィールドの属性を指定できます。

  • IsFacetable
    • ファセットとして利用可能か
  • IsFilterable
    • フィルタリングが可能か
  • IsKey
    • キーとなる値か
  • IsRetrievable
    • 結果として返却を行うか
  • IsSearchable
    • 検索の対象か
  • IsSortable
    • ソートが可能か

わかりやすいメソッド名となっていますね。

これだけのコードでインデックスの作成が完了するので、次は実際にインデックスへデータをアップロードしていきたいと思います。

// IndexOperationType.Upload を指定するとインデックスへのデータ追加
var operation = new IndexOperation(IndexOperationType.Upload, "id", "1")
    .WithProperty("status", "抱かれたい男 No.1 とムッシュと TaaS")
    .WithProperty("createdOn", DateTimeOffset.Now);

// データのアップロード
await client.PopulateAsync("tweets", new[] { operation });

今回はわかりやすくするためにツイートが保存された CSV 周りの処理を削除して、実際にデータのアップロードを行うコードだけ紹介しました。

ちなみに Azure Search のポータルから確認できるインデックスの状態はこんな感じです。1000 ツイートをインデックス化したのでドキュメント数はちゃんと 1000 になっていますね。

f:id:shiba-yan:20140822205131p:plain

これで検索を行う準備が出来たので、実際に Azure Search を使ってツイートの検索を行ってみます。

// 検索を行う場合は IndexQueryClient を使う
var client = new IndexQueryClient(connection);

// SearchQuery の引数が検索したい文字列、SearchField は検索対象のフィールド
var result = await client.SearchAsync("tweets", new SearchQuery("抱かれたい男")
    .SearchField("status")
    .Top(10));

foreach (var item in result.Body.Records)
{
    // Properties には IsRetrievable を呼び出したフィールドの値が入る
    Console.WriteLine("{0} - {1},{2},{3}", item.Score, item.Properties["id"], item.Properties["status"], item.Properties["createdOn"]);}

実行した結果は以下になります。パッと見は良い感じに日本語でも検索できている気がしますが、よく見ると検索キーワードが全く含まれていないツイートもヒットしていることがわかります。

f:id:shiba-yan:20140822205622p:plain

どうやら日本語で検索する場合には、検索キーワードをダブルクオートで囲む必要がありそうです。

今度は検索キーワードをダブルクオートで囲んでから検索を行った結果です。

f:id:shiba-yan:20140822205951p:plain

ちゃんとキーワードだけが含まれているツイートが返ってきました。

日本語もとりあえずは検索を行えるようで安心したので、面白そうな使い方も試してみたいと思います。