我申请这个blog是为了督促自己,把自己平时的一些想法和思考结果保留下来。 本博客所有内容均为原创,如有转载请注明作者和出处

利用Oracle的全文索引实现切词功能

上一篇 / 下一篇  2008-01-30 16:24:10 / 个人分类:ORACLE

今天在ITPUB上看到这样一个需求,给出一个中文语句,如何对其实现切词。

如果Oracle全文索引的切词可以满足需求的话,那么可以借用Oracle的功能来实现这个功能。

 

 

Oracle的全文索引本身具备中文分析、切词功能,否则就无法有效的对中文进行搜索,如果这个切词结果可以满足要求的话,那么可以自己封装一个函数,来借用Oracle的功能。

由于建立全文索引函数后,Oracle会将切词结果放到DR$index_name$I表中,因此获取这个表中的记录就可以得到最终的切词结果。

建立自定义函数的时候注意,由于这个操作包括很多DDL操作,因此如果希望这个函数可以在SQL中被调用,就必须使用自主事务

为了方便的选择CHINESE_LEXER还是CHINESE_VGRAM_LEXER,将MY_CHINESE_LEXER的创建放到了函数之外,这样方便对切词规则进行修改。这个过程也是唯一需要在建立自定义函数之前做的步骤。

下面是实现这个功能的建立的例子:

SQL> EXEC CTX_DDL.CREATE_PREFERENCE('MY_CHINESE_LEXER', 'CHINESE_VGRAM_LEXER')

PL/SQL过程已成功完成。

SQL> CREATE OR REPLACE FUNCTION F_SPLIT_CHINESE(P_INPUT IN VARCHAR2) RETURN VARCHAR2 AS
IE,E&t6{6nd2c6|0  2   PRAGMA AUTONOMOUS_TRANSACTION; V_RETURN VARCHAR2(32767);ITPUB个人空间U2P!M'Lv[
  3  BEGIN
]]``oq0  4   BEGINITPUB个人空间-`\R8b!w2lX0Ojr
  5    EXECUTE IMMEDIATE 'DROP TABLE T_TEMP_TABLE PURGE';ITPUB个人空间){&swg vT i7K
  6   EXCEPTIONITPUB个人空间N*b_8Hq#oL7^4c'vx
  7    WHEN OTHERS THENITPUB个人空间zS)\;v{0e-DY
  8     NULL;ITPUB个人空间4r&N6_I,[
  9   END;ITPUB个人空间P4[ A7rmj&X8iWU,K5u
 10  ITPUB个人空间dl0U];z)B
 11   EXECUTE IMMEDIATE 'CREATE TABLE T_TEMP_TABLE (STR VARCHAR2(4000))';ITPUB个人空间 I d,[f(iW$X
 12   EXECUTE IMMEDIATE 'INSERT INTO T_TEMP_TABLE VALUES (:STR)' USING P_INPUT;
~p_ d2h-~-F!l0 13   EXECUTE IMMEDIATE 'CREATE INDEX IND_T_TEMP_TABLE_STR ON T_TEMP_TABLE(STR) INDEXTYPE IS CTXSYS.CONTEXTITPUB个人空间$Jx.Tr4J.y
 14    PARAMETERS(''LEXER MY_CHINESE_LEXER'')';ITPUB个人空间6p4M{7o[/o#q9aF
 15   EXECUTE IMMEDIATE 'SELECT MAX(LTRIM(SYS_CONNECT_BY_PATH(TOKEN_TEXT, '',''), '',''))ITPUB个人空间?$^9^j7\;Q1E
 16    FROM
pO SZ7M0 17    (ITPUB个人空间2{$z6Gm c*CxA$gb
 18     SELECT TOKEN_TEXT, ROW_NUMBER() OVER(ORDER BY TOKEN_TEXT) RNITPUB个人空间Q2X K1nYD
 19     FROM DR$IND_T_TEMP_TABLE_STR$IITPUB个人空间(h|Yn v&T!c_
 20    )
e IZ3HWASpV0 21    START WITH RN = 1ITPUB个人空间OC}+E(m
 22    CONNECT BY PRIOR RN + 1 = RN' INTO V_RETURN;
#c+w8N9X:ikd9FW&C0 23   EXECUTE IMMEDIATE 'DROP TABLE T_TEMP_TABLE PURGE';
V0oBv{|1n6D8k0 24   RETURN V_RETURN;ITPUB个人空间E:K&vt p`y
 25  END;ITPUB个人空间~z0j"C,bv)W Q
 26  /

函数已创建。

SQL> SELECT F_SPLIT_CHINESE('测试一下中文切词') FROM DUAL;

F_SPLIT_CHINESE('测试一下中文切词')ITPUB个人空间"{suDiLLS
------------------------------------------------------------------------ITPUB个人空间8A1c$AJS C
测试,,切词,试一,文切,下中,一下,中文

SQL> EXEC CTX_DDL.DROP_PREFERENCE('MY_CHINESE_LEXER')

PL/SQL过程已成功完成。

SQL> EXEC CTX_DDL.CREATE_PREFERENCE('MY_CHINESE_LEXER', 'CHINESE_LEXER')

PL/SQL过程已成功完成。

SQL> SELECT F_SPLIT_CHINESE('测试一下中文切词') FROM DUAL;

F_SPLIT_CHINESE('测试一下中文切词')ITPUB个人空间 D-fCt i(u:v.H
-----------------------------------------------------------------------ITPUB个人空间jyT}@.r"[
测试,,切词,一下,中文

通过修改不同的LEXER语法,可以明显的看出CHINESE_VGRAM_LEXERCHINESE_LEXER在中文分词上的区别。关于二者区别的一些描述可以参考:http://yangtingkun.itpub.net/post/468/187632

需要注意的是,这个函数声明了自主事务,虽然可以在SQL中调用,但是并不意味着这个函数不修改数据库中的内容。

这个函数在调用的过程中会执行建表、建立索引、删除表等一系列操作。因此调用这个函数的SELECT语句,不但会引起数据库数据的变化,而且会导致DDL的发生,导致很多的递归调用、逻辑读和REDO的产生。这是在使用这个函数之前需要理解的。

最后,这个函数在10g环境中完成,如果在9i版本使用,需要将DROP语句中的PURGE语句去掉,否则会造成语法错误。

 


TAG:

不胜人生一场醉 引用 删除 bq_wang   /   2008-02-01 10:36:05
呵呵,谢谢了 ,知道有这么一个半死不活的功能和怎么用就行了
yangtingkun的个人空间 引用 删除 yangtingkun   /   2008-02-01 10:23:13
中文切词本身就是门深奥的学问,个人认为Oracle切成这样已经算不错了。

何况Oracle的目的是为了支持查询,而不是单纯为了切词。
不胜人生一场醉 引用 删除 bq_wang   /   2008-02-01 00:45:02
刚做了个测试
“建立自定义函数的时候注意,由于这个操作包括很多DDL操作,因此如果希望这个函数可以在SQL中被调用,就必须使用自主事务。”
在'CHINESE_VGRAM_LEXER'被切的惨不忍睹
在'CHINESE_LEXER'情况下被切成
DDL,SQL,包括,被,必须,操作,的,调用,函数,很多,建立,就,可以,如果,时候,使用,事务,希望,义,因此,由于,在,这个,中被,注意,自定,自主
还算有点意义,不过大量虚词还是含了进来,看样子Oracle的全文索引距离实用还是有很大差距啊
不胜人生一场醉 引用 删除 bq_wang   /   2008-02-01 00:01:04
是不是可以是说如果使用Oracle的全文索引作为网络搜索引擎或者数据库资料搜索的的话,还远远达不到实用的目的啊
yangtingkun的个人空间 引用 删除 yangtingkun   /   2008-01-31 23:38:18
CHINESE_VGRAM_LEXER的切词更细,可能有些感觉并不像一个词。

而CHINESE_LEXER则切词似乎更准确一些。

但是,这只是对切词而言。如果真的用来查询的时候,你可能就会觉得CHINESE_LEXER的切词粒度太宽泛,以至于很多关键词没有分离出来
不胜人生一场醉 引用 删除 bq_wang   /   2008-01-31 22:53:02
测试,词,切词,试一,文切,下中,一下,中文
切出来的词有意义吗
 

评分:0

我来说两句

显示全部

:loveliness: :handshake :victory: :funk: :time: :kiss: :call: :hug: :lol :'( :Q :L ;P :$ :P :o :@ :D :( :)

Open Toolbar