How to make search in app is more powerful than you think?
今天要介紹得早在Windows 8 的時候就推出了Search功能!但基本上不會有特別的需求需要用使用該API,在一次偶然的情況下發現了該API的一些特性以及功能!
在一般的APP中大致都是提供Class內的某個字串型別的屬性或參數作為搜尋的目標,而在Windows提供原生Search方式給開發人員使用。
- Indexed Folder
- Content indexer
分為以上兩種!接下來分別介紹兩個search的功能
Inedxed folder
Indexed Folder 是特殊的資料夾,需建立在Local端 ( AppliocationData.Current.LocaFolder ) !當該資料夾被建立的時候系統會將該folder加入系統的Indexer的搜尋資料夾中,最簡單的範例就是Windows 10 內建的Settings app(UWP版本的控制台)
如上圖所示,就是Setting的搜尋功能
上圖所示就是Indexing options,可以發現系統有不少檔案處理方式都採用Indexed folder的機制。
然後來看一下如何使用Indexed folder八~
使用Indexed的搜尋模式需要在APP的 Local端建立一Folder
private const string IndexedFolderName = "Indexed";
//中間掠過~
private async Task InitializeIndexedSearchAsync()
{
var localFolder = ApplicationData.Current.LocalFolder;
var indexedFolder = await localFolder.CreateFolderAsync(IndexedFolderName, CreationCollisionOption.OpenIfExists);
}
這樣就是基礎的初始化Indexed folder的功能!只要建立該Indexed的Folder就可以簡單使用到索引搜尋的功能~
UWP有提供 Windows.Storage來進行檔案和資料夾的操作,而在該namespace下(Windows.Storage.Search)還有提供進行搜尋的功能相關功能。其中有個非常好用的Class- QueryOption!
QueryOption如同字面意思可以對搜尋做些額外的選項,簡單Sample如下
public asyn Task QueryFileAsync()
{
var localFolder = ApplicationData.Current.LocalFolder;
var queryOptions = new QueryOptions(CommonFileQuery.DefaultQuery, new string[] { ".txt" });
var settings = await localFolder.CreateFileQueryWithOptions(queryOptions).GetFilesAsync();
}
使用QueryOption的constructor的時候就可以指定要使用Query的方式以及副檔名的指定!然後在搭配在StorageFolder的Query的相關API就可以做到File query的功能了!
接者有個可以輔助Indexed search的檔案結構 Application Content ( .appcontent-ms )主要格式是使用XML,簡單Sample如下
<?xml version="1.0" encoding="utf-8"?>
<IndexerSampleInformation>
<Properties xmlns="http://schemas.microsoft.com/Search/2013/ApplicationContent">
<Name>Sample 1</Name>
<Keywords>
<Keyword xml:lang="en-US">Sample 1 - keyword 1</Keyword>
<Keyword>Sample 1 - keyword 2</Keyword>
</Keywords>
<Comment>Sample 1 comment</Comment>
<AdditionalProperties>
<Property Key="System.Title">Sample 1 Title</Property>
<Property xml:lang="en-US" Key="System.Contact.EmailAddresses">
<Value>bryan@contoso.com</Value>
<Value>vincent@contoso.com</Value>
</Property>
</AdditionalProperties>
</Properties>
<IndexerSampleSpecificElement sc:IndexableContent="true"
xmlns:sc="http://schemas.microsoft.com/Search/2013/ApplicationContent">
The text included here will be indexed, enabling full-text search.
</IndexerSampleSpecificElement>
</IndexerSampleInformation>
這邊在Root node可以自訂名稱,並需要在Properties的部分給予namespace。如上Sample的XML中的IndexerSampleSpecificElement也是可以自訂的Node名稱,配合該Namespace以及IndexableContent = "true"就可以做到對該Node的Content進行Index的功能!
如果使用IndexerSampleSpecificElement這樣的寫法可以再額外設定內容格式!預設是Text的方式藉由ContentType的Attribute可以設定如下所示的類型。
- application/hta
- application/mac-binhex40
- application/vnd.ms-xpsdocument
- application/windows-appcontent+xml
- application/x-compress
- application/x-compressed
- application/x-gzip
- application/x-jtx+xps
- application/x-latex
- application/x-mplayer2
- application/x-ms-wmz
- application/x-stuffit
- application/x-tar
- application/x-zip-compressed
- application/xml
- audio/aiff
- audio/basic
- audio/mid
- audio/midi
- audio/mp3
- audio/mpeg
- audio/mpegurl
- audio/mpg
- audio/wav
- audio/x-aiff
- audio/x-mid
- audio/x-midi
- audio/x-mp3
- audio/x-mpeg
- audio/x-mpegurl
- audio/x-mpg
- audio/x-ms-wax
- audio/x-ms-wma
- audio/x-wav
- image/bmp
- image/gif
- image/jpeg
- image/pjpeg
- image/png
- image/vnd.ms-photo
- image/x-emf
- image/x-icon
- image/x-png
- image/x-wmf
- midi/mid
- model/vnd.dwfx+xps
- model/vnd.easmx+xps
- model/vnd.edrwx+xps
- model/vnd.eprtx+xps
- pkcs7-mime
- text/css
- text/html
- text/plain
- text/xml
- video/avi
- video/mpeg
- video/mpg
- video/msvideo
- video/quicktime
- video/x-mpeg
- video/x-mpeg2a
- video/x-ms-asf
- video/x-ms-asf-plugin
- video/x-ms-wm
- video/x-ms-wmv
- video/x-ms-wmx
- video/x-ms-wvx
- video/x-msvideo
接者把.appcontent-ms的檔案複製到Indexed folder就可以做到索引搜尋的功能了!如下C# code所示
private async Task InitializeIndexedSearchAsync()
{
var localFolder = ApplicationData.Current.LocalFolder;
var indexedFolder = await localFolder.CreateFolderAsync("Indexed", CreationCollisionOption.OpenIfExists);
var queryOptions = new QueryOptions(CommonFileQuery.DefaultQuery, new string[] { ".appcontent-ms" });
var settingsFolder = await Package.Current.InstalledLocation.GetFolderAsync("Settings");
var settings = await settingsFolder.CreateFileQueryWithOptions(queryOptions).GetFilesAsync();
foreach (var file in settings)
{
await file.CopyAsync(indexedFolder, file.Name, NameCollisionOption.ReplaceExisting);
}
}
使用索引搜尋可以使用在比較簡單的檔案格式(文字)較為複雜的格式就得使用接者介紹的ContentIndexer了。
<?xml version="1.0" encoding="utf-8" ?>
<AppSearchUWP>
<Properties xmlns="http://schemas.microsoft.com/Search/2013/ApplicationContent">
<Name>Color Setting</Name>
<Keywords>
<Keyword xml:lang="en-us">color</Keyword>
<Keyword xml:lang="en-gb">colour</Keyword>
<Keyword xml:lang="zh-tw">顏色</Keyword>
</Keywords>
<Comment>Choose the color of your app</Comment>
<AdditionalProperties>
<Property Key="System.Title">Title for color setting</Property>
</AdditionalProperties>
</Properties>
<FullContentSearch_ZhTW xmlns:sc="http://schemas.microsoft.com/Search/2013/ApplicationContent" sc:IndexableContent="true">
測試Abc
</FullContentSearch_ZhTW>
</AppSearchUWP>
這邊有個 xml:lang="zh-tw",如果在語系及地區沒有設定在中文語系的區域就算輸入該Keyword是不會出現該資訊的!
ContentIndexer
使用ContentIndexer的Class使App提供Property bags( 屬性袋 ? )提供給系統做index並且可搜尋化!Property bags全都是metadata的資料形式敘述。Property bag可以包含任何屬性在shell property system!
那該怎樣選擇哪種搜尋方式呢?請看下表
功能 | ContentIndexer | Indexed folder |
---|---|---|
資料如何進入索引(index) | app 主動推送資料,並且必須觀察確保indexing是成功建立的 | app建立檔案在硬碟上,Indexer會主動管理indexing流程 |
App須提供的資料形式 | property bag | Any |
索引優先程度控制 | 高優先序,並由app主要控制 | 無法控制索引建立優先序,可強制提高優先序藉由資料夾全域搜尋 |
重置後的行為 | 重新推送資料 | 系統自動重新建立 |
稍微解釋一下Shell property system,該System是在Windows的檔案敘述系統
***以上Code以及說明都有可能隨著Windows 10 的版本以及Visual Studio 2015版本有所調整!***
參考資料 MSDN, Searching private app data in windows 10
下次再分享Windows 10 的新技術拉~