简易USER_LEXER

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

你可能感兴趣的:(oracle)