Windows Search 4.0をC#から利用する Part2
次にAdvanced Query Syntax(AQS)を使う方法について。Part1はこっち。
AQSはWindows Search用(たぶん)の検索条件指定で使う構文で、たとえば「パンダ 白浜」と入れて両方のキーワードで検索するとか、ファイルの作成日で検索するとかできるやつです。インストールしたWindows Searchのヘルプの、検索条件の項目に詳しく説明があります。
で、Windows Searchのインデックス情報は、OLE DB経由でしかアクセスできないようなので、AQSをWindows SearchのOLE DBプロバイダ向けのSQL構文に変換して検索する必要があります。それは自力でやるんではなくて、ISearchQueryHelper Interfaceというものが既に用意されています。
http://msdn.microsoft.com/en-us/library/aa965451(VS.85).aspx
SDKの中に、C++とC#の両方でISearchQueryHelperを使用したサンプルコードがありました。これはWindows Search 3.x向けみたいですが、4でも使えます。
http://msdn.microsoft.com/en-us/library/bb286798(VS.85).aspx
Microsoft Windows Search 3.x SDK
http://www.microsoft.com/downloads/details.aspx?FamilyID=645300AE-5E7A-4CE7-95F0-49793F8F76E8&displaylang=en
こんな感じのコード↓
(いろいろ端折ってるのでこのままでは動きません。詳細はSDKの中のサンプルプロジェクトDSearchとかを見てください)
private void Search() { // Thie uses SearchAPI interop assembly CSearchManager manager = new CSearchManager(); CSearchCatalogManager catalogManager = manager.GetCatalog("SystemIndex"); CSearchQueryHelper queryHelper = catalogManager.GetQueryHelper(); queryHelper.QuerySelectColumns = @" System.Search.Rank, System.ItemFolderPathDisplay, System.ItemPathDisplay , System.ItemFolderNameDisplay , System.ItemName , System.FileExtension , System.FileName , System.ItemTypeText , System.ItemDate , System.DateAccessed , System.ItemAuthors, System.Size "; // Generate SQL from our parameters, converting the userQuery from AQS->WHERE clause string sqlQuery = queryHelper.GenerateSQLFromUserQuery("パンダ 白浜"); // --- Perform the query --- // create an OleDbConnection object which connects to the indexer provider with the windows application using (System.Data.OleDb.OleDbConnection conn = new OleDbConnection(queryHelper.ConnectionString)) { // open it conn.Open(); OleDbCommand command = new OleDbCommand(sqlQuery, conn); OleDbDataReader WDSResults = command.ExecuteReader(); int nReads = 0; int nResults = 0; while (WDSResults.Read()) { nResults++; if (offsetRows <= nResults && (nReads < maxRows || maxRows == 0)) { nReads++; DataRow dr = ds.Tables[0].NewRow(); for (int i = 0; i < WDSResults.VisibleFieldCount; i++) { dr[i] = WDSResults.GetValue(i); } ds.Tables[0].Rows.Add(dr); } else if (maxRows <= nReads) { //最大読み込み件数を超えたため終了 break; } } WDSResults.Close(); conn.Close(); } } /// <summary> /// 検索結果のDataSetを作成 /// </summary> /// <returns></returns> DataSet GetDataSet() { DataSet ds = new DataSet("DSearch"); ds.Tables.Add(new DataTable("Results")); ds.Tables[0].Columns.Add(new DataColumn("Rank", typeof(Int32))); ds.Tables[0].Columns.Add(new DataColumn("ItemFolderPathDisplay", typeof(string))); ds.Tables[0].Columns.Add(new DataColumn("ItemPathDisplay", typeof(string))); ds.Tables[0].Columns.Add(new DataColumn("ItemFolderNameDisplay", typeof(string))); ds.Tables[0].Columns.Add(new DataColumn("ItemName", typeof(string))); ds.Tables[0].Columns.Add(new DataColumn("FileExtension", typeof(string))); ds.Tables[0].Columns.Add(new DataColumn("FileName", typeof(string))); ds.Tables[0].Columns.Add(new DataColumn("ItemTypeText", typeof(string))); ds.Tables[0].Columns.Add(new DataColumn("ItemDate", typeof(DateTime))); ds.Tables[0].Columns.Add(new DataColumn("DateAccessed", typeof(DateTime))); ds.Tables[0].Columns.Add(new DataColumn("ItemAuthors", typeof(string))); ds.Tables[0].Columns.Add(new DataColumn("Size", typeof(Int32))); return ds; }
ちなみに、常にTOP句を指定しない限り、OleDbDataReaderではなくてDataAdapterを使うのは避けたほうがいいです。検索結果件数が数万件を超えたあたりから、結果の取得に10分以上かかったりします。
続く。。。Part3