しばやん雑記

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

Azure Search に追加された Data Source と Indexer を使って SQL Database から自動的に Index を作成する

ちょっと前に Azure Search について書いた時に、適当に流した Indexer 周りについて実際にコード書いていろいろ遊んでみたのでまとめます。

http://azure.microsoft.com/en-us/documentation/articles/search-api-indexers-2014-10-20-preview/

一応、作成したプロジェクトは GitHub に上げておきました。

間違って Azure Search の管理者キーを含んだまま上げてしまったんですが、ポータルから無効化しておいたので動きません。各自差し換えてください。

基本的な処理の流れとしては以下のようになります。

  1. 同名のカラムを持つ Index を作成
  2. 接続文字列から Data Source を作成
  3. Data Source と Index を指定して Indexer を作成
  4. 作成した Indexer を実行

順を追って解説していきます。

Index を作成

残念ながら Azure Search 側に SQL Database のスキーマを読み取って、自動的にいい感じにインデックスを作ってくれる機能が無かったので自分で作りました。

SQL Database でテーブルのスキーマを使ったことなかったんですが、割とあっさりできました。方法はいろいろあるっぽいですが、今回は INFORMATION_SCHEMA を叩いてみました。

SELECT
    COLUMN_NAME, DATA_TYPE
FROM
    INFORMATION_SCHEMA.COLUMNS
WHERE
    TABLE_SCHEMA = 'SalesLT' AND TABLE_NAME = 'Product'
ORDER BY ORDINAL_POSITION

実際にはパラメータ化クエリにしてコードに埋め込んでますが、実行してみると以下のような感じに。

いい感じにカラム名とデータ型が取れました。カラム以外に Azure Search ではキーが必要なので、プライマリキーを取っていたりしますが、コード見てもらう形で。

後はこの情報を使って Index を作成するのですが、SQL Database の型と Azure Search の型を合わせてあげる必要があるので注意。つまり対応してない型があるってことです。

Data Source を作成

本来なら RedDog.Search が対応していてもらいたい部分なんですが、Data Source と Indexer に関しては未実装なので手動で API を叩きます。

ただし RedDog.Search に便利なメソッドがあったので、それをそのまま使います。

connection.Execute(new ApiRequest("datasources", HttpMethod.Post)
{
    Body = new
    {
        name = "sampledb",
        type = "azuresql or docdb",
        credentials = new
        {
            connectionString = "SQL Database の接続文字列"
        },
        container = new
        {
            name = "[SalesLT].[Product]",
        }
    }
}).Wait();

特に説明するところのないコードなんですが、SQL Database の他にも DocumentDB をソースとして使えるみたいです。ただし接続文字列という概念は無さそうなので、どうやって使うのかは謎。

container に指定しているのは SQL Database の場合はテーブル名です。スキーマ名も省略せずに書いた方が良い気がしました。

Indexer を作成

ここまでで Index と Data Source が用意できたので、やっと Indexer を作成する準備が出来ました。と言っても、API を 1 つ叩くだけで終わります。

connection.Execute(new ApiRequest("indexers", HttpMethod.Post)
{
    Body = new
    {
        name = "sampleindexer",
        dataSourceName = "sampledb",
        targetIndexName = "product"
    }
}).Wait();

これもまた特に説明するところが無いコードですが、dataSourceName に作成済みの Data Source 名を、targetIndexName に作成済みの Index 名を指定して実行しているだけです。

Indexer の作成タイミングで実行スケジュールを指定できたりしますが、今回は簡単にするためにオンデマンド実行にします。

作成した Indexer を実行

これで Indexer が作成できたので、実際に動かしてみます。API も名前指定するだけで、とてもシンプル。

connection.Execute(new ApiRequest("indexers/sampleindexer/run", HttpMethod.Post)).Wait();

実行すると Azure Search が SQL Database に接続して、いい感じにデータを追加してくれます。

ポータルから確認するとデータが追加されていることが確認出来ました。Indexer を Azure Search 側で持ってくれていて、しかも Azure のサービスとの親和性の高さは今後が期待出来そうな感じです。

そろそろ Elasticsearch の勉強会とかに参加して知識を増やしたい感あります。