パーソナルツール
現在の場所: ホーム ブログ Categories mail
« 2018January »
Su Mo Tu We Th Fr Sa
  1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31      
このBlogについて
 代表の向井田ことMUKAです。当ブログサイトでは、MAGICやDB2に関する技術者向け情報を公開しています。お気軽にお立ち寄り下さい。
最近のエントリ
twitter / 新RT機能を英語モードで・・・ muka 2009年11月19日
twitter / List Widget muka 2009年11月03日
twitter API / Retweet の仕様が・・・ muka 2009年10月30日
twitter API / Lists muka 2009年10月24日
IBM Rational Software Conference 2009 と アジャイル開発 muka 2009年10月08日
twitter API / geoタグ! muka 2009年10月01日
Twitter Developers Meetup in Tokyo muka 2009年09月11日
Club DB2 2009/9/4 muka 2009年09月05日
最近のコメント
Re:Club DB2 2009/8/29 muka 2009年09月01日
Re:Club DB2 2009/8/29 SIM 2009年08月31日
最近のトラックバック
Club DB2 8/29の感想エントリと今後の予定 Unofficial DB2 BLOG 2009年09月01日
カテゴリ
misc (47)
dbMAGIC (47)
DB2 (47)
mail (47)
Web (47)
twitter (47)
 

mail

一つ上に移動
メールアーカイブシステムや、メールサーバ構築など、メールソリューションに関連する話題

DB2 9 を利用したメール・アーカイブ・システムの開発 (6)


XQuery(SQL/XML )による検索処理


 前回までは、XMLデータに変換したメールデータをDB2(Ver 9.1、9.5)に格納するところまでは前回までで説明させて頂きました。
 今回は、格納したメールの検索方法について述べてみたいと思います。
 検索方法については、幾つかの方法があるのですが、まずは、標準的な、XQuery(SQL/XML )によるもの、その後、全文検索エンジンを使用したものについてそれぞれ説明したいと思います。

 まず、リレーショナル表として配置してあるカラムを使用することにより、通常のSQLによる検索が可能です(当たり前ですね)。
 下のSQL文はリレーショナル表のカラムとして設置した日付カラム(MAIL_DATE)を使用して2008年5月1日からのメールを10件取得するためのものです。

select MAIL_ID, MAIL_DATE
from MAIL_ARC.MAIL_DB
where MAIL_DATE >= '20080501000000'
order by MAIL_DATE fetch first 10 rows only

 この結果は、下図のようになります。

ma_041.jpg

 次に、XMLカラムの属性に対して検索条件を追加してみましょう。
 例えば、メールヘッダの日付属性(Date)に「Apr」のあるものを条件として追加するには下記のようにSQL文を変更します。

(補足すると、カラム「MAIL_DATE」に格納する時刻はJSTに変換して格納しているので、JSTの5月1日に送信されたメールは、他の標準時で4月30日の日付となることもありえます。)

select c.MAIL_ID, c.MAIL_DATE
from MAIL_ARC.MAIL_DB c
where c.MAIL_DATE >= '20080501000000' and
 xmlexists(
'declare default element namespace
 "http://schemas.eternaldesign.jp/oides/mail2xml" ;
  $i/RFC822[Header/Date[contains(.,"Apr")]]'
passing c.MAIL_DATA as "i")

order by c.MAIL_DATE fetch first 10 rows only

 少し複雑になりますが、「from」句で表「MAIL_ARC.MAIL」を「c」として扱い、「xmlexist」関数の中でXMLカラムである「c.MAIL_DATA」を変数「i」に渡しています。
 格納されているXMLドキュメントに名前空間が設定されている場合は「declare ~」以下の指定が必要です。
 日付属性のXPathは「/RFC822/Header/Date」ですから、「contain」関数で「Apr」を含むものを指定しています。
 今度は、実際にメールのヘッダの日付値に「Apr」が含まれているのかを表示してみましょう。
 Select句の中に「xmlquery」関数を挿入することにより、XMLの任意の情報を出力させることが可能になります。

select c.MAIL_ID, c.MAIL_DATE,
xmlquery(
'declare default element namespace
  "http://schemas.eternaldesign.jp/oides/mail2xml" ;
$i/RFC822/Header/Date' passing c.MAIL_DATA as "i") as DATE

from MAIL_ARC.MAIL_DB c
where c.MAIL_DATE >= '20080501000000' and
xmlexists(
'declare default element namespace
 "http://schemas.eternaldesign.jp/oides/mail2xml" ;
 $i/RFC822[Header/Date[contains(.,"Apr")]]'
 passing c.MAIL_DATA as "i")
order by c.MAIL_DATE fetch first 10 rows only

 結果はXMLタイプのオブジェクトとして返されます。

ma_042.jpg

 照会結果画面の「...」ボタンを押して中身の確認が可能です。

ma_043.jpg

 XQueryは出力結果をFLOWER式(「フラワー」と読む)を使用することによって自由な形式で出力が可能なのですが、もしテキストにシリアライズするのであれば、上記の太線部分は下記のように書き換えることも可能です(「xmlserialize」関数と「fn:data」関数を使用)。

xmlserialize(
xmlquery(
 'declare default element namespace
  "http://schemas.eternaldesign.jp/oides/mail2xml" ;
  $i/RFC822/Header/fn:data(Date)' passing c.MAIL_DATA as "i")
 as varchar(40)) as DATE
ma_044.jpg

 あとは組み合わせで複雑な条件を指定することも可能です。
 開発したアプリケーションでは、検索条件の指定によりダイナミックにクエリ文を生成します。

ma_045.jpg

メールアーカイブの検索画面(NSEを使わない=非標準の場合)

ちなみに 「大文字と小文字を同一視」というチェックボックスを入れた場合は、

$i/RFC822[Header/Date[contains(.,"Apr")]]

を下記のように変更しています。

$i/RFC822[Header/Date[contains(fn:upper-case(.),"APR")]]


Net Search Extenderによる検索処理


 Net Search Extender(以下NSE)は、DB2用の全文検索用エンジンです。別途インストール操作が必要になります。DB2のデータベースに対し、「テキスト索引」と呼ばれる専用の索引を作成し、高速検索を可能にします。インストール後は、各種保守用のコマンドにより、有効化したり、索引の作成や更新を行います。
 当然ながらXML などの構造化されたテキスト・フォーマットにも対応しており、XPathを指定した任意のノードに対するテキスト検索も可能です。
 NSEの使い方としては「Contain関数」が代表的なもので、Where句の中で指定することにより該当する行を高速に検索します。
 もし先のクエリーをNSEを使用したものに変えたとすると、下記のようになります。

select c.MAIL_ID,c.MAIL_DATE,
 xmlserialize(xmlquery(
 'declare default element namespace
  "http://schemas.eternaldesign.jp/oides/mail2xml" ;
  $i/RFC822/Header/fn:data(Date)' passing c.MAIL_DATA as "i")
 as varchar(40)) as DATE
 from MAIL_ARC.MAIL_DB c
where c.MAIL_DATE >= '20080501000000' and
contains(MAIL_DATA,' section("/RFC822/Header/Date") "Apr" ')=1
order by c.MAIL_DATE fetch first 10 rows only

 「section」を指定することにより、XMLのノードを指定することが可能です。(指定しなければ、任意のテキストを検索します。)
 複数の条件をAND条件で検索する場合は下記のような構文になります。

contains(MAIL_DATA,' section("/RFC822/Body/Data/Body")  "見積"
 & section("/RFC822/Body/Data/Body") "訪問" ')=1
XQueryなどとは、微妙に式の連結方法や構文が異なりますが、たとえ混在しても動作するというのは面白いものだと思います。
 ついでにNSEモードに変更したときの検索画面を掲載しておきます。(アプリケーションとしては、こちらのモードでの利用が主たるものになります。)

ma_046.jpg

メールアーカイブの検索画面(NSEを使う=標準の場合)


 NSEの最大のメリットはなんと言っても「高速な検索」です。純粋なXQuery(SQL/XML)による検索ではストレスが多少あったものも、処理をNSEに置き換えることにより、全くなくなりました。また、大文字や小文字の混在を気にしなくても良いというメリットもあります。メールアドレスなど、リレーショナルデータでは、大文字・小文字が混在すると、違うデータ扱いになりますが、NSEの検索では、これを気にしなくても済むようになりす。
 その他、Highlight関数による検索結果の表示機能など有用な機能も幾つかあります。

 さて、良いところばかり並べましたが、NSEを使う上での問題点を上げると、「テキスト索引の更新に多少時間がかかる」ということです。
 メールアーカイブの場合は、定期的な処理として、メールの取り込み時にテキスト索引も一緒に更新しますから、特に大きな問題にはなり得ませんが、リアルタイム性が要求されるようなシステムの場合はテキスト索引の更新処理についても若干の考慮が必要になりそうです。(索引の更新は差分で行われますが、データ量が大きくなればなるほど索引の更新処理に要する処理時間は顕著になるような気がします。)




カテゴリ
DB2
mail