読者です 読者をやめる 読者になる 読者になる

miso_soup3 Blog

主に ASP.NET 関連について書いています。

Azure Search で自炊本 PDF を検索

Azure Search ASP.NET MVC C#

by:dots.女子部 Advent Calendar 2016 - Qiita

自炊した本PDFファイルをいくつか用意し、Azure Search で中身を検索する実装を試してみました。

大まかな流れは、次の通りです。

  • Azure Blob Storage に PDF ファイルを入れる
  • Azure Search を用意する
  • 検索する Web アプリを作成し、HTTP で Azure Search の API から本を検索する

試してみた結果ですが、なぜかいくつかの PDF がインデックスする際にエラーとなってしまい、 原因が分からず、結局 6 冊分しか検索できないアプリになってしまいましたorz

今回使用したツールなど:

  • OS: Windows 10
  • Azure で使うサービス
    • Azure Blob Storage
    • Azure Search
  • IDE: Visual Studio 2017 RC
  • Web Framework: ASP.NET MVC(ASP.NET Code ではなく)
  • C#

GitHub サンプルはこちらgist

作成した Webアプリ

画面

f:id:miso_soup3:20161208170936p:plain

「深層」で検索してみる

f:id:miso_soup3:20161208170943p:plain

Azure Search

Azure Search とは、Azure のサービスの1つで検索 SaaS です。 Azure Search では検索対象となるデータソースを指定できるのですが、そのうちの1つとして、Azure Blob Storage があります。 PDF・Office ファイル・CSV・JSON などを入れた Azure Blob Storage を指定すると、それを検索対象としてインデックスを作成し、HTTP 経由で検索を提供します。 この Azure Blob を対象とする機能は、今までプレビューだったのですが、11月末に一部GAとなりました。

また、PDF の場合は Azure Search が PDF の中のテキストを抽出してくれます。

詳しくはこちら:

以下の表は、各ドキュメント形式に関して実行される処理と、Azure Search によって抽出されるメタデータのプロパティをまとめたものです。 Azure Blob Storage のインデックスを Azure Search で作成する

サンプル PDF ファイルの用意

まず、Azure Blob Storage を用意し、そこにサンプル PDF ファイルをアップロードします。

ローカルにて用意した PDF ファイル群:

f:id:miso_soup3:20161208171025p:plain

アップロードには、「AzCopy」コマンドが便利です。AzCopy を使用してストレージにデータをコピーまたは移動する | Microsoft Docs

AzCopy をインストールし、次のようにコマンドを実行します。

AzCopy /Source:C:\Users\hhyyg\Desktop\books2{←PDFがあるフォルダパス} /Dest:https://{your account}.blob.core.windows.net/{conainer 名} /DestKey:{Azure Blob Storage の key}} /S /SetContentType

アップロード後、Microsoft Azure Storage Explorer 等のツールで Blob の中身を確認します。

f:id:miso_soup3:20161208171035p:plain

なぜここで、ファイル名が数字になっていて、ファイル数が6つしかないのか、というと、この後の「インデックス」作成の手順でエラーが発生したからです。 エラーについては最後に記載しました。

Azure Search の用意

次に Azure Search の用意です。Azure ポータルにて、Azure Search を作成した後、「データのインポート」を選択します。

f:id:miso_soup3:20161208171135p:plain

データの接続で、先ほど PDF をアップロードした Azure Blob Storage を選択します。

f:id:miso_soup3:20161208171146p:plain

すると、通知欄に”データソースをサンプリングしています”と表示されます。

f:id:miso_soup3:20161208171154p:plain

ここで成功すると、「インデックス」を設定するフォームが表示されます。

f:id:miso_soup3:20161208171201p:plain

↑の画像では、インデックス名が「temp」となっていますが、「booksindex」みたいに分かりやすい名前を付けます。この「インデックス名」は、後のコードで参照します。

設定の内容ですが、画像のように、「content」以外を「取得可能」にチェック、「content」のみを「検索可能」にチェックします。

f:id:miso_soup3:20161208171210p:plain

「content」には、PDF から抽出したテキストが入るため、膨大なサイズの値になります。これを「取得可能」にしてしまうと HTTP でアクセスした際に膨大な値がレスポンスに入ってしまいます。なのでチェックを外します。 また、「content」の「検索可能」にチェックを入れるのは、PDFから抽出したテキストを検索対象とするためです。

次に、「アナライザー」タブをクリックし、「content」の「アナライザー」を、「日本語 - Lucene」に設定します。これは、「日本語 - Micorosoft」でもかまいません。 PDF の内容が日本語であれば、このどちらかを選択するのが良いと思います。

f:id:miso_soup3:20161208171218p:plain

次は、「インデクサー」の作成です。ここでは、「1度」を選択します。 Azure Blob Storage の内容が変更になる可能性がある場合は、「毎時間」や「毎日」を選択し、インデックスの内容を更新するようにします。

f:id:miso_soup3:20161208171225p:plain

操作が完了すると、「インデクサー」の画面から成否が表示されます。ここで成功となれば、Azure Search の準備は完了です。

f:id:miso_soup3:20161208171229p:plain

検索してみる

検索の結果は Azure のポータルから確認できます。Azure Search の「Search エクスプローラー」を開き、「検索」をクリックすると検索結果を確認できます。

f:id:miso_soup3:20161208171235p:plain

結果として、metadata_storage_name PDF のファイル名や、metadata_storage_path Azure Blob Storage の URL(base64で変換されています。)が格納されていることを確認できます。 アプリを作成する場合は、この URL を SDK などで叩いて HTTP アクセスにより検索結果を得ます。

ここで、実際の PDF のテキスト内容が格納されていない理由は、先ほどの「インデックス」の設定で「content」の「取得可能」にチェックを入れなかったためです。 もし、チェックと入れていると、ここで大量のテキストデータがここに出力されることになります。

Web アプリを作成

検索を試してみたところで、Web アプリを作成します。今回は ASP.NET MVC 5 で作成しましたが、HTTP 経由で Azure Search にアクセスするので他のプラットフォーム・フレームワークでも作成できます。

Visual Studio で ASP.NET MVC 5 のベースを作成した後、NuGet パッケージ「Microsoft.Azure.Search」をインストールします。 インストール後、Web.config にて、次のようにキーを設定します。

このキーの名前は、後の実装によるので、実装とともに変更して構いません。キーの値は、ポータルより確認できます。

f:id:miso_soup3:20161208171244p:plain

サンプルは GitHub にありますので、ここでは注意点だけ記載します。

ハイライト

検索結果をハイライトして表示するには、リクエストを送信する際にどのフィールドをハイライトしたいか指定します。 Azure Search SDK を使った今回は、次のように「content」をハイライト対象に設定しました。

return new SearchParameters()
{
    SearchMode = SearchMode.Any,
    IncludeTotalResultCount = true,
    HighlightFields = new string[] { "content" },
    Top = 20
};
base64 デコード

レスポンスにある「metadata_storage_path」フィールドには、Azure Blob Storage の URL がエンコードされて格納されます。 実際に PDF を取得するには、この Azure Blob Storage の URL にアクセスする必要があるのですが、デコードは次のようにします。

System.Text.Encoding.UTF8.GetString(HttpServerUtility.UrlTokenDecode("{metadata_storage_path の値}".ToString()));

エラー

インデックスの際のエラーですが、発生した原因は分からず、以下の可能性が怪しいとみています。

  • ファイル名が日本語だから?
  • PDF ファイル内のコンテンツが日本語?変な値がある?

f:id:miso_soup3:20161208171041p:plain

エラーメッセージ: 説明データ ソースからインデックス スキーマを削除するときにエラーが発生しました: "Error processing blob 'https://misobooksst.blob.core.windows.net/mycontainer/180日でグローバル人材になる方法.pdf' with content type '': 422

Azure Search では日本語関連の問題に出会うことが多いです。 現在このエラーの原因の調査をお願いしています。(12/9)