はじめに
こんにちは。ACS 事業部の奥山です。 Azure で AI Service の一つとして提供されている Azure Cognitive Search を試してみましたので、備忘録を兼ねてブログにしておきます。
全文検索(Full Text Search)とは
wikiによると「複数の文書(ファイル)から特定の文字列を検索すること。」とのこと、身近な例だとGoogle や Yahoo!の検索が有名ですね。Elastic Searchなどが最近よく利用されているのを見かけますが、ログの解析や文書(ドキュメント)の検索など様々な活用方法があります。
Cognitive Search + SQL Server の準備
まずは、テストデータの準備(SQL Server)
※cognitive search からみるとデータソースになります。
単純なテーブルを用意し検証用データとして100万レコード用意します。
CREATE TABLE mytbl01 ( myid INT PRIMARY KEY IDENTITY (1, 1), remark01 NVARCHAR (MAX), remark02 NVARCHAR (MAX), remark03 NVARCHAR (MAX) );
100万レコード作成するT-SQL。それぞれのremarkに日本語の文章をいれておきます。
DECLARE @p_NumOfRows BIGINT SELECT @p_NumOfRows=1000000; -- 100万レコード WITH Base AS ( SELECT 1 AS n UNION ALL SELECT n+1 FROM Base WHERE n < CEILING(SQRT(@p_NumOfRows)) ), Expand AS ( SELECT 1 AS c FROM Base AS b1, Base AS b2 ), Nums AS ( SELECT ROW_NUMBER() OVER(ORDER BY c) AS n FROM Expand ) INSERT INTO mytbl01 SELECT -- n, 'Azure Cognitive Search (旧称 Azure Search) は、Web、モバイル、エンタープライズ アプリケーションに、プライベートで異種のコンテンツに対するリッチな検索エクスペリエンスを組み込むためのインフラストラクチャ、API、およびツールを開発者に提供するクラウド検索サービスです。', 'Azure Cognitive Search (旧称 Azure Search) は、Web、モバイル、エンタープライズ アプリケーションに、プライベートで異種のコンテンツに対するリッチな検索エクスペリエンスを組み込むためのインフラストラクチャ、API、およびツールを開発者に提供するクラウド検索サービスです。', 'Azure Cognitive Search (旧称 Azure Search) は、Web、モバイル、エンタープライズ アプリケーションに、プライベートで異種のコンテンツに対するリッチな検索エクスペリエンスを組み込むためのインフラストラクチャ、API、およびツールを開発者に提供するクラウド検索サービスです。' FROM Nums WHERE n <= @p_NumOfRows OPTION (MaxRecursion 0);
100万レコード入っているのを確認。
1> select count(*) from mytbl01; 2> go ----------- 1000000 (1 rows affected)
REST APIを利用して インデクサー の作成
基本的にはこの手順になります。REST APIとして用意されているのが使いやすくて良いですね。
データソースを定義
curl $MYHOSTNAME/datasources?api-version=2020-06-30-Preview \ -H 'Content-Type: application/json' -H 'api-key: '$MYAPIKEY \ -d @sample_data_def-sqlsrv.json
※sample_data_def.json には dbへの接続情報を設定
インデックスに検索フィールドを追加
テーブル定義に合わせて検索に利用したいフィールドを追加します。
※日本語を含む列に日本語用の analyzer を設定します。 (ja.microsoft or ja.lucene)
cat sample_index.json { "name" : "my-example-ix", "fields": [ { "name": "myid", "type": "Edm.String", "key": true, "searchable": true }, { "name": "remark01", "type": "Edm.String", "searchable": true, "filterable": true }, { "name": "remark02", "type": "Edm.String", "searchable": true, "filterable": true, "analyzer": "ja.microsoft" }, { "name": "remark03", "type": "Edm.String", "searchable": true, "filterable": true, "analyzer": "ja.lucene" } ] } curl $MYHOSTNAME/indexes?api-version=2020-06-30-Preview \ -H 'Content-Type: application/json' -H 'api-key: '$MYAPIKEY \ -d @sample_index.json
インデクサーを構成して実行
curl $MYHOSTNAME/indexers?api-version=2020-06-30 \ -H 'Content-Type: application/json' -H 'api-key: '$MYAPIKEY \ -d @sample_indexer.json
インデクサーの状態を確認
curl $MYHOSTNAME/indexers/example-mysql-idxr/status?api-version=2020-06-30 \ -H 'Content-Type: application/json' -H 'api-key: '$MYAPIKEY
Azure ポータル画面からも確認できます。
今回のデータの場合は100万レコードでおよそ15分でした。
※日本語の文章は remark1 + remark2 + remark3 を合わせて500文字程度。
検索クエリの基礎
2 つの Lucene ベースのクエリ言語(SimpleとFull)。
※Simpleが既定値
※あいまい検索などを利用したい場合はFullを利用する
コマンド例
例:simple query
cat query_sample/simple01.json { "search": "*", "queryType": "simple", "select": "myid, remark01", "count": true } curl -H 'Content-Type: application/json' -H 'api-key: '$MYAPIKEY \ $MYHOSTNAME/indexes/my-example-ix/docs/search?api-version=2020-06-30 \ -d @query_sample/simple01.json
例:full query
cat query_sample/full01.json { "search": "*", "select": "myid, remark01, remark02, remark03", "count": true, "queryType": "full", "searchMode": "all", "top": "5" } curl -H 'Content-Type: application/json' -H 'api-key: '$MYAPIKEY \ $MYHOSTNAME/indexes/my-example-ix/docs/search?api-version=2020-06-30 \ -d @query_sample/full01.json
※Queryの書き方はしっかり勉強する必要があります。これはどのツールや技術でも同じですね。
テキストの分析
以下のAPIで analyzer がどのように文章を分割するか確認することができます。
cat query_sample/analyzer_sample.json { "text": "11月29日は雨でした。", "analyzer": "ja.lucene" } $ curl -H 'Content-Type: application/json' -H 'api-key: '$MYAPIKEY \ $MYHOSTNAME/indexes/my-example-ix/analyze?api-version=2020-06-30 \ -d @query_sample/analyzer_sample.json | jq . { "@odata.context": "https://cognitive-search-23177.search.windows.net/$metadata#Microsoft.Azure.Search.V2020_06_30.AnalyzeResult", "tokens": [ { "token": "11", "startOffset": 0, "endOffset": 2, "position": 0 }, { "token": "月", "startOffset": 2, "endOffset": 3, "position": 1 }, { "token": "29", "startOffset": 3, "endOffset": 5, "position": 2 }, { "token": "日", "startOffset": 5, "endOffset": 6, "position": 3 }, { "token": "雨", "startOffset": 7, "endOffset": 8, "position": 5 } ] }
"11月29日は雨でした。" は "11", "月", "29", "日", "雨" の 5つに分解されているのがわかります。
REST API で indexへのデータの追加
以下のようにindexへデータを追加することができます。
cat query_sample/sampledata1.json { "value": [ { "@search.action": "mergeOrUpload", "myid": "900000001", "remark01": "昨日の天気は曇りでした。", "remark02": "今日の天気は雨です。", "remark03": "明日の天気は晴れです。" } ] } curl $MYHOSTNAME'/indexes/my-example-ix/docs/index?api-version=2020-06-30' \ -H 'Content-Type: application/json' -H 'api-key: '$MYAPIKEY \ -d @query_sample/sampledata1.json
簡単に SQL Server(SQL) と Cognitive Search のクエリを比べてみる
※当然ですが、SQL Serverはフルスキャンされるので時間がかかります。
SQL Server
remark01 に "今日" という文字列を含むレコード数を集計してみます。 集計に17秒かかっています。
Cognitive Search
こちらも同様に "今日" という文字列を含むレコード数を集計してみます。
cat query_sample/query.json { "search": "今日", "count": true, "queryType": "full", "searchMode": "all" } curl -H 'Content-Type: application/json' -H 'api-key: '$MYAPIKEY \ $MYHOSTNAME/indexes/my-example-ix/docs/search?api-version=2020-06-30 \ -d @query_sample/query.json -o out.json -w "response_time:%{time_total}" response_time:0.219822
約0.2秒で返ってきています。(これだけで 単純に Cognitive Search の方が早いとは言えないですが。)
まとめ
以上、簡単ですがAzure での 全文検索 (Cognitive Search) の利用方法についての紹介でした。 全文検索を利用する方法として Elastic Search などがありますが、 Azure が SaaS として提供してくれていることで簡単に導入ができるところが良いですね。Azureで全文検索やるなら是非利用したいですね。
今回はRDBのデータを登録して、簡単に検索できることの確認でしたが、Cognitive Search は 非構造化データ (画像やPDF)なども取り扱うことが可能になっています。このあたりも今後調査・検証していきたいと思います。
(参考)Cognitive Search を利用される場合は、この記事のワークショップがお勧めです。
最後に
私達ACS事業部はAzure・AKSを活用した内製化のご支援をしております。ご相談等ありましたらぜひご連絡ください。
また、一緒に働いていただける仲間も募集中です!
切磋琢磨しながらスキルを向上できる、エンジニアには良い環境だと思います。ご興味を持っていただけたら嬉しく思います。