GF76  ﾌｧｲﾙ検索ﾃｰﾌﾞﾙ
	ファイルパス	FILEPATH	X(256)

ファイルパス には、ファイル名を含むフルパスになっています。
FILE_DATASTORE を使ってみます。

①使用できるように、FILE_ACCESS_ROLE を付与します。
  ここでは、public にしてしまいます。

（実行はSYSユーザで行う）
	connect sys/system as sysdba

EXECUTE CTXSYS.CTX_ADM.SET_PARAMETER('FILE_ACCESS_ROLE','public');

******* 本当は、ROLE を設定して、そのROLEをユーザーに与える。 *******
BEGIN
	CTXSYS.CTX_ADM.SET_PARAMETER('FILE_ACCESS_ROLE','TOPCAT');
END;
*********************************************************************

②-1.FILE_DATASTORE のプリファレンスを作成します。
  これは、サンプル的に、FILEPATH に、jspファイルのｱﾄﾞﾚｽを用意して、それにｲﾝﾃﾞｯｸｽを作成します。
  FILE_DATASTORE で、PATH属性を指定すると、索引付けは単純なファイル名のみになり、パスと結合することはできません。
  ファイルが複数のフォルダまたはディレクトリに存在する場合、PATH属性を設定せずに、
  索引付けされた列にPATHを含む完全なファイル名を指定する必要があります。

EXEC CTX_DDL.DROP_PREFERENCE('GF76_TXT')

BEGIN
	CTX_DDL.CREATE_PREFERENCE('GF76_TXT','FILE_DATASTORE');
--	CTX_DDL.SET_ATTRIBUTE('GF76_TXT','PATH','/mydocs');
END;

②-2.インデックスの作成。
  CTXSYS.CONTEXT で、先ほどの、DATASTORE を指定します。
--CREATE INDEX GF76_TXT_IDX ON GF76(FILEPATH)
--	INDEXTYPE IS CTXSYS.CONTEXT
--	PARAMETERS ('DATASTORE GF76_TXT');

③.フィルターの解除
  jspは、XMLなので、フィルタ処理を行わない様に、NULL_FILTER を使用します。
  プレーン・テキスト、HTMLまたはXMLドキュメントの索引付けに使用します。
  WORDやEXCELを解析する場合は、デフォルトの AUTO_FILTER で構いません。(つまり指定する必要がない)

--DROP INDEX GF76_TXT_IDX;
--
--CREATE INDEX GF76_TXT_IDX ON GF76(FILEPATH)
--	INDEXTYPE IS CTXSYS.CONTEXT
--	PARAMETERS ('DATASTORE GF76_TXT FILTER CTXSYS.NULL_FILTER');

④.日本語用のﾚｸｻｰも追加します。
  JAPANESE_LEXER と JAPANESE_VGRAM_LEXER がありますが、JAPANESE_LEXER を使用します。
  これは、文をワードに変換するために、内部ディクショナリが参照されます。
  トークンを固定文字数ごとに切り出す JAPANESE_VGRAM_LEXER と比較して、
  小型の索引の生成、問合せ応答時間の短縮、実ワード・トークンの生成による問合せ精度の向上 という
  利点がありますが、索引付けに要する時間は、JAPANESE_VGRAM_LEXERを使用した場合より長くなります。

BEGIN
	CTX_DDL.CREATE_PREFERENCE('JPN_LX','JAPANESE_LEXER');
END;

DROP INDEX GF76_TXT_IDX;

CREATE INDEX GF76_TXT_IDX ON GF76(FILEPATH)
	INDEXTYPE IS CTXSYS.CONTEXT
	PARAMETERS ('DATASTORE GF76_TXT FILTER CTXSYS.NULL_FILTER LEXER JPN_LX');


⑤全文検索用のトークンが参照できる。GF76_TXT_IDX はさっき作ったインデックスを指定します。
select count(*) from DR$GF76_TXT_IDX$I ;
SELECT TOKEN_TEXT FROM DR$GF76_TXT_IDX$I ORDER BY TOKEN_TEXT;


⑥検索してみます。
SELECT * FROM GF76 WHERE CONTAINS (FILEPATH, 'upload') > 0;


SELECT * FROM GF76 WHERE CONTAINS (FILEPATH, 'LEE & UTSUNOMIYA & MURAKAMI & 費目') > 0;


SELECT * FROM GF76 WHERE CONTAINS (FILEPATH, '使用検索') > 0;

=====================================================
テキスト索引の同期化
EXEC CTX_DDL.SYNC_INDEX( 'GF76_TXT_IDX' );

テキスト索引のメンテナンス
EXEC CTX_DDL.OPTIMIZE_INDEX( 'GF76_TXT_IDX','FAST' );

削除されて既に検索対象表に存在していないトークンを削除
EXEC CTX_DDL.OPTIMIZE_INDEX( 'GF76_TXT_IDX','FULL' );

=====================================================
⑦SNIPPET
  ドキュメントの用語索引を作成するには、CTX_DOC.SNIPPETプロシージャを使用します。
  用語索引とは、問合せ語句とその前後のテキストを含むテキストの断片（フラグメント）です。
  この用語索引は、マークアップされた問合せキーワードを前後のテキストと一緒に戻すため、
  文脈付きキーワード（KWIC）としても知られており、ユーザーは問合せキーワードを文脈で評価できます。

※通常は、問合せの後で処理するドキュメントを特定してから使用する

SELECT UNIQ FROM GF76 WHERE CONTAINS (FILEPATH, '使用検索') > 0;
結果、UNIQ = 190726 の SNIPPET を求める。
select CTX_DOC.SNIPPET('GF76_TXT_IDX','190726','使用検索') from dual

実際には、プライマリキーを JOIN することで、検索結果の 用語索引
を取り出すことができますが、何か別の方法を考えるべき？

select CTX_DOC.SNIPPET('GF76_TXT_IDX',UNIQ,'使用検索')
	from GF76
	WHERE CONTAINS (FILEPATH, '使用検索') > 0;


スコアを戻すには、SCORE演算子を指定します。
逆順に表示すれば、スコアの高い順に表示できます。

select SCORE(1),CTX_DOC.SNIPPET('GF76_TXT_IDX',UNIQ,'使用検索')
	from GF76
	WHERE CONTAINS (FILEPATH, '使用検索',1) > 0
	ORDER BY SCORE(1) DESC ;


表示件数を絞るには、副問合せで、ROWNUM を使います。
件数を絞り込んでから、SNIPPET を表示させます。

select SCR,CTX_DOC.SNIPPET('GF76_TXT_IDX',UNIQ,'使用検索') as TXT
from (
	select SCORE(1) as SCR,UNIQ
		from GF76
		WHERE CONTAINS (FILEPATH, '使用検索',1) > 0
		ORDER BY SCORE(1) DESC
)
where rownum < 11

=====================================================
