公司项目须要实现馆藏库的全文检索,可是只有一个查询,若是使用lucene的话不太方便,经过查找资料,发现oracle自带全文检索功能。通过测试,oracle实现全文检索很方便,很实用。oracle
注意:本例子针对于表中某一字段的全文检索。如ceshi表中name字段下全部数据的检索。oop
环境:oracle11g,oracle链接为search,表为ceshi,字段有id,name测试
1:进行准备工做,oracle全文检索须要ctxsys用户的支持,其实主要须要使用ctxsys用户下的ctx_ddl这个包,因此咱们使用system帐户解锁stxsys用户。优化
1.1:使用system帐户创建链接spa
1.2:解锁stxsys用户,分别执行如下两个命令。并将权限赋予arc_master用户(注意:arc_master用户是我本身新建的用户,可使用不一样的用户名).net
对ctxsys用户解锁,以得到ctx_ddl包的操做权。进入system用户,输入以下命令,解锁ctxsys用户blog
alter user ctxsys account unlock;排序
将ctx_ddl包的操做权限赋给arc_master用户。索引
grant execute on ctx_ddl to arc_master; token
2:准备工做完成以后,使用arc_master用户链接(链接如图1),开始测试。
2.1:创建测试表
create table ceshi(
id number,
name varchar2(50)
);
2.2:插入测试数据
insert into ceshi values(111,'重庆市沙坪坝区');
insert into ceshi values(211,'成都市青羊区');
insert into ceshi values(311,'北京市西城区');
insert into ceshi values(411,'重庆市两江新区');
insert into ceshi values(511,'上海市浦东新区金桥镇');
insert into ceshi values(611,'上海东方明珠');
insert into ceshi values(711,'江苏省无锡市国家软件园');
insert into ceshi values(811,'成都市天府软件园');
2.3:建立分析器,建立一个“chinese_lexer”分析器,名称为my_lexer。
exec ctx_ddl.create_preference ('my_lexer', 'chinese_vgram_lexer');
这个分析器的做用就是name字段的全部数据分词,以便于后面建立索引。如图所示:
词法分析器有3种类型:
* 'CHINESE_VGRAM_LEXER'仅用于中文,提取标示符更大,无效标示符较多;
* 'CHINESE_LEXER' 仅用于中文,效率高一些更准确可靠一些;建议使用
* 'BASIC_LEXER'仅用于英文;
2.4:建立过滤词组,,好比对公司名称进行检索时,确定不但愿输入“有限公司”、“公司”等关键词时,也会有搜索结果。
exec ctx_ddl.create_stoplist('my_stoplist');
自定义须要过滤的词组,建立了一个名为“my_stoplist”的过滤词组,“有限公司”、“股份有限公司”这两个词组不会被建立为索引。
exec ctx_ddl.add_stopword('my_stoplist','有限公司');
exec ctx_ddl.add_stopword('my_stoplist','股份有限公司');
2.5:建立索引,在ceshi_INDEX表中的name字段上建立索引,索引类系那个为context类型,该索引用到的分析器为前面定义的my_lexer,该索引用到的过滤词组为前面定义得my_stoplist。
create index ceshi_INDEX on ceshi(name) indextype is CTXSYS.CONTEXT parameters('lexer my_lexer stoplist my_stoplist');
2.6:使用索引,此时的数据是没有通过排序。经过如下的查询语句就能够很快的查处所需的内容。
select * from ceshi where contains(name,'北京市')>0;
2.7:虽然内容查出来了,不过数据是无序的。有的时候须要根据状况决定查询结果出现的前后顺序。能够按照关键字的匹配程度排序,这里的score是oracle全文检索对关键字的匹配程度所计算的分数,contains里的最后一个参数“1”就是对这个分数的一个标识。
select score(1),y.* from ceshi y where contains(name,'软件',1)>0 order by score(1) desc;
2.8:经过以上步骤基本就完成了oracle检索。不过当咱们添加新数据的时候,新数据并无建立新的索引,此时须要索引同步和索引优化。
索引同步
exec ctx_ddl.sync_index('ceshi_index');
索引优化
exec ctx_ddl.optimize_index('ceshi_index','full');
3:最后一个问题,就是用户输入的关键字也须要进行分词,由于前面分词图能够看到,词被分红一块一块,若是用户输入的词不拆分,有可能查不出来数据。(最后这一步骤的实现不理解)
首先须要先建立一个POLICY过程,这里建立了一个名称为my_policy的policy过程,分析器用到了前面建立的my_lexer分析器
exec CTX_DDL.CREATE_POLICY('MY_POLICY', LEXER => 'my_lexer');
create or replace function p_split_chinese(p_input in varchar2)
return varchar2 as
v_tab CTX_DOC.TOKEN_TAB;
v_return VARCHAR2(323767);
begin
CTX_DOC.POLICY_TOKENS('my_policy',p_input,v_tab);
for i in 1..v_tab.count loop
v_return := v_return || ',' || v_tab[i].token;
end loop;
return LTRIM(v_return,',');
end;
select F_SPLIT_CHINESE('重庆天府') from dual;
F_SPLIT_CHINESE('重庆天府')
最后,经过这些步骤,咱们就能够根据jdbc来实现功能了。
参考博文:http://blog.csdn.net/linfssay/article/details/7679353