USER_LEXERによる Simple 2-Gram Lexer (検索対象がVARCHAR2列)
Oracle Text の USER_LEXER による Simple 2-Gram Lexer の実装サンプルで
す。検索対象はVARCHAR2列。データベース・キャラクタセット上の全てのコー
ドポイントを単純に2文字ずつ区切ってトークンを生成します。主な仕様は、
・ 一文字での検索も実行可能
・ 記号文字(全角の#$%、半角の#$%など)による検索も可能
・ 大文字と小文字の同一視は行わない(=大文字と小文字を区別して検
索)
・ 全角と半角の同一視は行わない(=全角と半角を区別して検索)
・ ワイルドカード検索には非対応
となっています。
/*------------------------------------------------
* ユーザ作成
*----------------------------------------------*/
CONNECT / AS SYSDBA
CREATE USER testctx IDENTIFIED BY testctx;
GRANT connect, resource, ctxapp TO testctx;
ALTER USER ctxsys IDENTIFIED BY ctxsys ACCOUNT UNLOCK;
CONNECT ctxsys/ctxsys
GRANT EXECUTE ON CTX_ULEXER TO testctx;
/*------------------------------------------------
* INDEX_PROCEDURE for 2-Gram Lexer
* INPUT_TYPE=VARCHAR2
*----------------------------------------------*/
CONNECT testctx/testctx
CREATE OR REPLACE PROCEDURE ind_ngram
(
v_a IN VARCHAR2,
v_b IN OUT VARCHAR2,
v_c IN BOOLEAN
)
IS
v_len NUMBER;
BEGIN
v_len := LENGTH(v_a);
v_b := '<tokens>';
FOR i IN 1 .. v_len - 1 LOOP
v_b := v_b || '<word>' || SUBSTR(v_a, i, 2) || '</word>';
END LOOP;
v_b := v_b || '<word>' || SUBSTR(v_a, v_len, 1)
|| '</word></tokens>';
END ind_ngram;
/
/*------------------------------------------------
* QUERY_PROCEDURE for 2-Gram Lexer
*----------------------------------------------*/
CONNECT testctx/testctx
CREATE OR REPLACE PROCEDURE que_ngram
(
v_a IN VARCHAR2,
v_b IN CTX_ULEXER.WILDCARD_TAB,
v_c IN OUT VARCHAR2
)
IS
v_len NUMBER;
BEGIN
v_len := LENGTH(v_a);
v_c := '<tokens>';
IF v_len >= 2 THEN
FOR i IN 1 .. v_len - 1 LOOP
v_c := v_c || '<word>' || SUBSTR(v_a, i, 2) || '</word>';
END LOOP;
ELSIF v_len = 1 THEN
v_c := v_c || '<word wildcard="1">' || v_a || '%</word>';
END IF;
v_c := v_c || '</tokens>';
END que_ngram;
/
/*------------------------------------------------
* 検索対象表作成
*----------------------------------------------*/
CONNECT testctx/testctx
CREATE TABLE test_tab
(
id NUMBER PRIMARY KEY,
text VARCHAR2(4000)
);
INSERT INTO test_tab VALUES (1, 'オラクルOracle');
INSERT INTO test_tab VALUES (2, 'Oracle');
INSERT INTO test_tab VALUES (3, 'z');
INSERT INTO test_tab VALUES (4, '¥/※○×\/*+-');
INSERT INTO test_tab VALUES (5, 'Oracle Text');
INSERT INTO test_tab VALUES (6, 'Oracle Text');
INSERT INTO test_tab VALUES (7, 'Oracle Text');
INSERT INTO test_tab VALUES (8, 'OracleText');
COMMIT;
/*------------------------------------------------
* 索引作成
*----------------------------------------------*/
CONNECT testctx/testctx
BEGIN
CTX_DDL.CREATE_PREFERENCE('my_lexer', 'user_lexer');
CTX_DDL.SET_ATTRIBUTE
('my_lexer', 'index_procedure', 'ind_ngram');
CTX_DDL.SET_ATTRIBUTE('my_lexer', 'input_type', 'varchar2');
CTX_DDL.SET_ATTRIBUTE
('my_lexer', 'query_procedure', 'que_ngram');
END;
/
BEGIN
CTX_DDL.CREATE_STOPLIST('my_stoplist', 'basic_stoplist');
END;
/
CREATE INDEX test_idx ON test_tab(text)
INDEXTYPE IS ctxsys.context
PARAMETERS
('
LEXER my_lexer
STOPLIST my_stoplist
');
/*------------------------------------------------
* 検索
*----------------------------------------------*/
CONNECT testctx/testctx
COLUMN text FORMAT A80
SELECT * FROM test_tab WHERE CONTAINS (text, 'ルo') > 0;
SELECT * FROM test_tab WHERE CONTAINS (text, 'オラ') > 0;
SELECT * FROM test_tab WHERE CONTAINS (text, 'e') > 0;
SELECT * FROM test_tab WHERE CONTAINS (text, 'z') > 0;
SELECT * FROM test_tab WHERE CONTAINS (text, 'Ora%') > 0;
SELECT * FROM test_tab WHERE CONTAINS (text, '○×') > 0;
SELECT * FROM test_tab WHERE CONTAINS (text, '○○') > 0;
SELECT * FROM test_tab WHERE CONTAINS (text, '\/*') > 0;
SELECT * FROM test_tab WHERE CONTAINS (text, '\/-') > 0;
SELECT * FROM test_tab WHERE CONTAINS (text, '\\\/\*') > 0;
SELECT * FROM test_tab WHERE CONTAINS (text, '\\\/\-') > 0;
SELECT * FROM test_tab WHERE CONTAINS (text, 'Oracle Text') > 0;
SELECT * FROM test_tab WHERE CONTAINS (text, 'Oracle\ Text') > 0;
SELECT * FROM test_tab WHERE CONTAINS (text, ' T') > 0;
SELECT * FROM test_tab WHERE CONTAINS (text, 'T ') > 0;
SELECT * FROM test_tab WHERE CONTAINS (text, 'T') > 0;
SELECT * FROM test_tab WHERE CONTAINS (text, 'Oracle Tex
t') > 0;
SELECT * FROM test_tab WHERE CONTAINS (text, ' T') > 0;
SELECT * FROM test_tab WHERE CONTAINS (text, '\ \ ') > 0;
SELECT * FROM test_tab WHERE CONTAINS (text, 'Oracle\ \ Text') > 0;
SELECT * FROM test_tab WHERE CONTAINS (text, 'Oracle\ Text') > 0;
/*
※ 問合せ演算子はバックスラッシュ「\」でエスケープすることで検索でき
ます。
*/
http://otn.oracle.co.jp/otn_pl/otn_tool/code_detail?n_code_id=1933