全文検索
Full text search..
文章に含まれる文字列で検索したい場合、Grepとかspotlight検索とか使ったりしますよね。(windowsのは何て呼ぶんでしょうね)
Cache'で「含まれる文字列の検索」を行う場合は、グローバルを$Orderや$Queryでアクセスして、包含 [
演算で該当したものを見つけたりします。でも、この方法では検索の度に全データにアクセスするので、データ量が増えてくると遅くなってしまいます。これはGrepと同じです。
そこで、あらかじめインデックスグローバルを作っておき、検索時にはインデックスグローバルにアクセスするだけで該当するデータを見つけることができるようにしていました。
最近のCache'では全文検索機能が搭載されたので、面倒なく簡単に「含まれる文字列の検索」ができるようになりました。
今回は、この全文検索を試してみます。
%Text.Textクラスを使ってクラスを作る
全文検索は %Text.Textクラスで提供されています。日本語で使用する場合は、%Text.Textを継承した %Text.Japaneseクラスを使用します。
マニュアル上の全文検索の説明としては、 %Text.Textクラスの説明が一番詳しいのではないかと思います。
例として、製品マスタ・クラス Test.Product を作成します。この中のDescriptionプロパティに対して全文検索を行えるようにします。
/// 全文検索のテスト
Class Test.Product Extends %Persistent
{ /// 商品コード
Property Code
As %String(MAXLEN =
10) [
Required ];
Index CodeIndex On
Code [ Unique ];
/// 製品名
Property Name
As %String [
Required ];
/// 製品説明
Property Description
As %Text (MAXLEN =
36000,
LANGUAGECLASS =
"%Text.Japanese");
Index DescriptionIndex
On "Description(KEYS)" [
Type = bitmap ];
}
最後の2行(太字の部分)がキモです。簡単に説明します。
Descriptionプロパティは%Text型で文字列長は3.6万文字、解釈を行うクラスとして%Text.Japaneseを指定しました。 また、このインデックスとしてDescriptionIndexを作成し、%Text.Japaneseクラスが解釈した結果であるKEYについてインデックスを作成します。
今回はビットマップ型インデックスとしました。
データを投入する
作成したTest.Productクラスにデータを登録します。 ターミナルから以下のように入力します。
USER> Set x=##class(Test.Product).%New()
USER> Set
x.Code="ISW11K"
USER> Set x.Name="DIGNO"
USER> Set
x.Description="WiMAX搭載スーパースリム、防水対応スマートフォン。スリムボディーに、「充実機能」と「使いやすさ」を凝縮。WiMAX搭載で高速モバイル通信を実現し、インターネット接続を快適にします。単体での利用はもちろん、本体をWi-Fiルーターとして利用することも可能です。"
USER> Do x.%Save()
オブジェクトですので、SQL文でも登録できます。 ターミナルでSQL Shellを使って、Insert文で登録します。
USER>Do $SYSTEM.SQL.Shell() SQL Command Line
Shell ----------------------------------------------------
The
command prefix is currently set to: <<nothing>>. Enter q to quit, ?
for help.
USER>>Insert into Test.Product (Code, Name,
Description) values ('ISW13F','ARROWS Z','脅威の激速Quad Core CPU搭載。All in
oneハイスペック防水スマートフォン。スマートフォンの頭脳でもあるコアCPUを4つ搭載しながら、省電力化も実現。圧巻のグラフィック性能や13.1Mカメラ、HD動画の視聴も快適に楽しめます。指紋認証やプライバシーモードなどのセキュリティ機能、便利な本格辞書も搭載。')
1 Row Affected statement prepare time: 0.0473s, elapsed execute
time: 0.0061s.
---------------------------------------------------------------------------
黒のままだとわかりにくいので、入力した文字は 赤にしてみました。
全文検索、実行
データを登録したので、早速検索を実行してみます。 全文検索は %CONTAINS() 関数を使用します。
引き続きターミナルのSQL ShellでSQL文を入力します。
USER>> SELECT * from Test.Product where Description %Contains('モバイル')3.
SELECT * from Test.Product where Description %Contains('モバイル')ID
Code Description Name 1 ISW11K
WiMAX搭載スーパースリム、防水対応スマートフォン。スリムボディーに、「充実機能」と「使いやすさ」を凝縮。WiMAX搭載で高速 モバイル通信を実現し、インターネット接続を快適にします。単体での利用はもちろん、本体をWi-Fiルーターとして利用することも可能です。
DIGNO 1 Rows(s) Affected statement prepare time: 0.0012s,
elapsed execute time: 0.0012s.
---------------------------------------------------------------------------
USER>> SELECT * from Test.Product
where Description %Contains('スマートフォン')ID Code Description
Name 1 ISW11K WiMAX搭載スーパースリム、防水対応 スマートフォン。スリムボディーに、「充実機能」と「使いやすさ」を凝縮。WiMAX搭載で高速モバイル通信を実現し、インターネット接続を快適にします。単体での利用はもちろん、本体をWi-Fiルーターとして利用することも可能です。
DIGNO 2 ISW13F 脅威の激速Quad Core CPU搭載。All in oneハイスペック防水 スマートフォン。スマートフォンの頭脳でもあるコアCPUを4つ搭載しながら、省電力化も実現。圧巻のグラフィック性能や13.1Mカメラ、HD動画の視聴も快適に楽しめます。指紋認証やプライバシーモードなどのセキュリティ機能、便利な本格辞書も搭載。
ARROWS Z 2 Rows(s) Affected statement prepare time: 0.0597s,
elapsed execute time: 0.0050s.
---------------------------------------------------------------------------
(着色は筆者による)
このように、全文検索が動作することが確認できました。
動作の推定
しかし、この動きでは like '%文字列%'
演算とどう違うのかわかりません。 というか、動きとしては同一の結果が得られます。
違いはデータ量が増えた時に初めて出てきます。 %CONTAINSによる検索は、インデックスを使って検索するため、速度の劣化が少ないのです。
そのインデックスとはどのようなものか見てみましょう。
システム管理ポータルで、対象ネームスペースのグローバルを確認すると次のようになっています。
Test.ProductD 行の表示を押して内容を見てみます
![](imgF.gif)
登録したデータが格納されていることが分かります。 前の画面に戻って、Test.ProductI 行の表示を押して内容を見てみます
![](img11.gif)
こちらが、インデックスのようです。
^Test.ProductI("CodeIndex")以下がCodeプロパティに対するインデックス、 ^Test.ProductI("DescriptionIndex")以下がDescriptionプロパティに対するインデックスです。
下図のように ^Test.ProductI("DescriptionIndex")以下はDescriptionの内容が2文字ずつ格納されていることが分かります。
このことから「モバイル」で検索すると、モバイルを2文字ずつに分解し、「モバ」 and 「バイ」 and 「イル」
の検索を行なっていると推定されます。 検索する文字が長くなると、全文検索には多くのand演算が必要になります。 bitmapインデックスはand/or演算が高速に行えるため、全文検索のインデックスにbitmapインデックスを使用することが勧められているのだと思われます。
|