【引用】Oracle全文检索方面的研究(全10)

4、操作实例

4.1 单列与多列支持中文检索

Create table mytable1(id number primary key, doc1 varchar2(400),doc2 clob,doc3 clob);

Insert into mytable1 values(1,'今天的天气很不错,我想去逛街','今天是星期天,不用上班。天天好心情','明天是星期一,要上班。心情不好');

Insert into mytable1 values(2,'天是蓝色的,万里无云。天气非常好。','天是多云的,天气看起来要下雨了。不适宜出门','天正在下雨,大雨倾盆。不能出门。');

Insert into mytable1 values(3,'this is a text','this is a word','this is a pdf');

Commit;

--先删除引用

begin

ctx_ddl.drop_preference('my_chinese_vgram_lexer');

ctx_ddl.drop_preference('my_chinese_lexer');

end;

--支持中文分词

Begin

ctx_ddl.create_preference('my_chinese_vgram_lexer', 'chinese_vgram_lexer');

ctx_ddl.create_preference('my_chinese_lexer', 'chinese_lexer');

End;

--先删除引用

begin

ctx_ddl.drop_preference('my_multi');

end;

--多列查询,如果仅仅是单列,则不用设置这个类型

Begin

Ctx_ddl.create_preference('my_multi', 'multi_column_datastore');

Ctx_ddl.set_attribute('my_multi', 'columns', 'doc1, doc2, doc3');

End;

drop index myindex;

--单列查询,支持中文的索引建立

Create index myindex on mytable(docs)

indextype is ctxsys.context

parameters ('datastore ctxsys.default_datastore lexer foo.my_chinese_lexer')

drop index idx_mytable;

--多列查询,支持中文的索引的建立

Create index idx_mytable on mytable1(doc1)indextype is ctxsys.context

parameters('datastore my_multi lexer foo.my_chinese_lexer');

--chinese_lexer词法分析器下的结果,三列都可以查询

Select * from mytable1 where contains(doc1, '今天')>0;  --检索到第一条数据

Select * from mytable1 where contains(doc1, '不适宜')>0; --检索到第二条数据

Select * from mytable1 where contains(doc1, '适宜')>0; --检索不到数据,他的分词技术太简单,将‘不适宜’作为一个词了

Select * from mytable1 where contains(doc1, '出门')>0;  --检索到第二条数据

Select * from mytable1 where contains(doc1, 'this is a word')>0;  --检索到第三条数据,中英文适用

--chinese_vgram_lexer词法分析器下的结果,

--chinese_vgram_lexer词法分析器虽然没那么智能,但检索结果往往比较符合我们的要求,

--如:“不适宜”这个词语应该拆分为“不适宜”和“适宜”两个词语,而不是单独的作为一个词语,

--chinese_vgram_lexer可以查询的到,而chinese_lexer不可以。

drop index idx_mytable;

--多列查询,支持中文的索引的建立

Create index idx_mytable on mytable1(doc1)indextype is ctxsys.context

parameters('datastore my_multi lexer foo.my_chinese_vgram_lexer');

--chinese_vgram_lexer词法分析器下的结果,三列都可以查询

Select * from mytable1 where contains(doc1, '今天')>0;  --检索到第一条数据

Select * from mytable1 where contains(doc1, '不适宜')>0; --检索到第二条数据

Select * from mytable1 where contains(doc1, '适宜')>0; --检索到第二条数据,这个分词虽然效率低点,但检索结果还可以

Select * from mytable1 where contains(doc1, '出门')>0;  --检索到第二条数据

Select * from mytable1 where contains(doc1, 'this is a word')>0;  --检索到第三条数据,中英文适用

--对于多列查询,更新列操作

--只更新从表,看是否能查到更新的信息

Update mytable1 set doc2='adladlhadad this datastore when your text is stored test' where id=2;

--同步更新索引

Begin

Ctx_ddl.sync_index('idx_mytable');

End;

--可见,虽然你检索是三个列,但是你更新的不是索引对应的那列(doc1),同步了索引也是不起作用的

Select * from mytable1 where contains(doc1,'adladlhadad')>0; --没有记录

--更新与doc1列原来相同内容(实际内容不变,只有操作而已)

Update mytable1 set doc1='天是蓝色的,万里无云。天气非常好。' where id=2;

--再同步更新索引

Begin

Ctx_ddl.sync_index('idx_mytable');

End;

--再查询一次

Select * from mytable1 where contains(doc1,'adladlhadad')>0; --有结果,可见,对于其他查询的列(非索引对应的列)的更新操作,可以连同索引对应的列一起更新,只是不改变索引的内容即可做到同步索引就可以出现效果了。

4.2 本地磁盘检索

create table mytable3(id number primary key, docs varchar2(2000));

insert into mytable3 values(111555,'1.txt');

insert into mytable3 values(111556,'1.doc');

insert into mytable3 values(111557,'1.xls');

insert into mytable3 values(111558,'1.pdf');

insert into mytable3 values(111559,'2.txt');

insert into mytable3 values(111560,'2.doc');

insert into mytable3 values(111561,'2.xls');

insert into mytable3 values(111562,'2.pdf');

commit;

--先删除引用

begin

ctx_ddl.drop_preference('COMMON_DIR');

end;

--建立 file datastore

begin

ctx_ddl.create_preference('COMMON_DIR','FILE_DATASTORE');

ctx_ddl.set_attribute('COMMON_DIR','PATH','D:\search');

end;

--先删除索引

drop index myindex3;

--建立索引,8个文件,内容简单,耗时1.5s

create index myindex3 on mytable3(docs) indextype is ctxsys.context parameters ('datastore COMMON_DIR lexer foo.my_chinese_lexer');

select * from mytable3 where contains(docs,'text')>0; --查询,支持txt

select * from mytable3 where contains(docs,'pdf')>0; --查询,支持pdf

select * from mytable3 where contains(docs,'excel')>0; --查询,支持excel

select * from mytable3 where contains(docs,'word')>0; --查询,支持doc

select * from mytable3 where contains(docs,'文本')>0; --查询,支持中文

select * from mytable3 where contains(docs,'文档')>0; --查询,支持中文

select * from mytable3 where contains(docs,'阅读')>0; --查询,支持中文pdf

select * from mytable3 where contains(docs,'这是Excel')>0; --查询,支持中文

--暂时测试支持doc,txt,xls,pdf

--更新了文件内容2.txt

select * from mytable3 where contains(docs,'这个测试用的文本')>0; --查询无更新好数据

--不同步索引,无效

--同步更新索引

Begin

Ctx_ddl.sync_index('myindex3');

End;

--再次查询

select * from mytable3 where contains(docs,'测试')>0; --还是无效

--用相同的值取代2.txt然后再同步索引

Update mytable3 set docs='2.txt' where id=111559;

--再同步索引

--同步更新索引

Begin

Ctx_ddl.sync_index('myindex3');

End;

--再次查询

select * from mytable3 where contains(docs,'测试')>0; --结果出现,可见,单更新文件内容,同步索引是无效的,索引认的是数据库纪录,数据库纪录改变,索引才会更新

--新增加文件,结果雷同。关键是要更新数据库纪录,即使改了文件内容,也要用相同的值update数据库纪录一次。

4.3 检索结果高亮显示

Create table my_high (id number primary key, docs varchar2(1000));

insert into my_high values (1, 'this is a oracle text example. And oracle is the key word.');

insert into my_high values (2, '

oracle textthis is a oracle ctx_doc hightlight example.');

commit;

/

--建立索引

create index ind_m_high on my_high(docs) indextype is ctxsys.context;

--返回结果的偏移量

set serverout on

declare

v_restab ctx_doc.highlight_tab;

begin

ctx_doc.highlight('ind_m_high', 1, 'oracle', v_restab, true);

for i in 1..v_restab.count loop

dbms_output.put_line('begin with: ' || v_restab(i).offset || ' length: ' || v_restab(i).length);

end loop;

end;

/

begin with: 11 length: 6

begin with: 36 length: 6

ctx_doc.highlight参数说明:

ctx_doc.highlight(索引,数据库中的ID, 搜索关键字, 指明返回的偏移量是针对纯文本格式还是针对HTML格式, true);

true or false: 对比PLAINTEXT设置为FALSE和TRUE的区别可以发现,对于HTML所有的标识部分,Oracle统一认为长度等于2。

对于True:

oracle textthis is a oracle ctx_doc hightlight example.,认为是2个长度,false的话就全部纪录,认为总共有7个字符长度。

要在sqlplus执行

4.4 具体测试

4.4.1 基本的全文检索

--先删除引用

begin

ctx_ddl.drop_preference('my_chinese_vgram_lexer');

ctx_ddl.drop_preference('my_chinese_lexer');

end;

--支持中文分词

Begin

ctx_ddl.create_preference('my_chinese_vgram_lexer', 'chinese_vgram_lexer');

ctx_ddl.create_preference('my_chinese_lexer', 'chinese_lexer');

End;

Begin

Ctx_ddl.create_preference('F_DOCNEWS_Preference', 'multi_column_datastore');

Ctx_ddl.set_attribute('F_DOCNEWS_Preference', 'columns', 'F_CONTENT,F_DESCRIPTION,F_TITLE');

End;

drop index f_content_index;

Create index f_content_index on T_DOCNEWS(F_CONTENT)

indextype is ctxsys.context

parameters('datastore F_DOCNEWS_Preference lexer foo.my_chinese_lexer');

Select * from T_DOCNEWS where contains(F_CONTENT,'菲律宾')>0; --有结果,

4.4.2 带动态摘要的高亮全文检索

--先删除引用

begin

ctx_ddl.drop_preference('my_chinese_vgram_lexer');

ctx_ddl.drop_preference('my_chinese_lexer');

end;

--支持中文分词

Begin

ctx_ddl.create_preference('my_chinese_vgram_lexer', 'chinese_vgram_lexer');

ctx_ddl.create_preference('my_chinese_lexer', 'chinese_lexer');

End;

--先删除索引

drop index f_content_index;

--新建索引,默认属性,无过滤器,支持中文高级分词

Create index f_content_index on T_DOCNEWS(F_CONTENT)

indextype is ctxsys.context

parameters('datastore ctxsys.default_datastore filter ctxsys.null_filter section group

ctxsys.html_section_group lexer foo.my_chinese_lexer');

?--以下开始准备建立存储过程,先定义数组类型

CREATE or replace TYPE f_content_arr AS OBJECT(

id NUMBER ,

url varchar2(255),

title varchar2(255),

abstractcontent varchar2(255)

);

--定义数组变量

CREATE or replace type f_content_arr_re as table of f_content_arr;

--定义存储过程

create or replace procedure f_content_pro (keyword in varchar,v_cfjg out f_content_arr_re) is

v_restab ctx_doc.highlight_tab;

begin

DECLARE

i number;

s clob;

startnum number;

endnum number;

v_res_fun T_DOCNEWS%rowTYPE;

cursor c_fun is

select *  from T_DOCNEWS where contains(F_CONTENT,keyword)>0;

BEGIN

i := 0;

v_cfjg := f_content_arr_re();

open c_fun;

LOOP

fetch c_fun

into v_res_fun;

EXIT WHEN c_fun%NOTFOUND;

i := i + 1;

s := v_res_fun.F_CONTENT;

v_cfjg.EXTEND;

ctx_doc.highlight('f_content_index', v_res_fun.F_ID, keyword, v_restab, false);

--只取第一个,没有loop循环

startnum:=v_restab(1).offset;

if v_restab(1).offset > 30 then

begin

startnum := v_restab(1).offset-30 ;

end;

end if;

if v_restab(1).offset <= 30 then

begin

startnum := 1 ;

end;

end if;

if length(s)-v_restab(1).offset > 30 then

begin

endnum := v_restab(1).offset+30 ;

end;

end if;

if length(s)-v_restab(1).offset <= 30 then

begin

endnum := length(s) ;

end;

end if;

v_cfjg(v_cfjg.count) := f_content_arr(v_res_fun.F_ID,v_res_fun.F_URL,v_res_fun.F_TITLE,substr(s,startnum,endnum-startnum));

dbms_output.new_line();

END LOOP;

end;

EXCEPTION

WHEN TOO_MANY_ROWS THEN

DBMS_OUTPUT.PUT_LINE('TOO_MANY_ROWS');

WHEN OTHERS THEN

DBMS_OUTPUT.PUT_LINE(sqlerrm);

end f_content_pro;

--在此,全文检索存储过程定义完毕

--以下是sqlplus调用

declare

s f_content_arr_re;

begin

f_content_pro('菲律宾',s);

END;

Java后台调用存储过程并返回参数代码:

public ArrayList search(String keyword) {

ArrayList list = new ArrayList();

Connection conn = null;

ResultSet rs = null;

CallableStatement stmt = null;

DocNews docnews;

try {

conn = DBPool.getConnection();

stmt = null;

String procName = new StringBuffer().append("{ call f_content_pro(?,?) } ").toString();

stmt = conn.prepareCall(procName);

stmt.setString(1, keyword);

stmt.registerOutParameter(2, Types.ARRAY, "F_CONTENT_ARR_RE");

stmt.execute();

ARRAY arr = (ARRAY) stmt.getArray(2);

rs = arr.getResultSet();

while (rs.next()) {

STRUCT struct = (STRUCT) rs.getObject(2);

Object[] obs = struct.getAttributes();

docnews = new DocNews();

docnews.setId(((BigDecimal)obs[0]).longValue());

docnews.setUrl((String)obs[1]);

docnews.setTitle((String)obs[2]);

docnews.setAbstractcontent((String)obs[3]);

list.add(docnews);

}

if (stmt != null) {

stmt.close();

}

if (conn != null) {

conn.close();

}

} catch (Exception e) {

e.printStackTrace();

}

return list;

}

注:在java中调用方法,除了在项目里加入class12.jar包以外,还需要加入Oracle自带的orai18n.jar包,如果仅仅是执行main方面,则可以,但如果是web项目,则要将orai18n.jar包加入到jdk的%jdk%\jre\lib\ext目录中才行。如果没有orai18n.jar这个包会造成检索调用存储过程返回结果是乱码(???三个问号)。

4.4.3 检索简单界面图

5.检索性能

执行以下索引

Create index f_content_index on T_DOCNEWS(F_CONTENT)

indextype is ctxsys.context

parameters('datastore F_DOCNEWS_Preference lexer foo.my_chinese_lexer');

总共5272条新闻,总耗时61s

合计约一分钟5000条

查询仅需200多毫秒

oracle怎么搜索10条,【摘引】Oracle全文检索方面的研究(全10)相关推荐

  1. oracle 取任意一条数据,oracle随机取一条数据详解

    Oracle 随机获取N条数据 当我们获取数据时,可能会有这样的需求,即每次从表中获取数据时,是随机获取一定的记录,而不是每次都获取一样的数据,这时我们可以采取Oracle内部一些函数,来达到这样的目 ...

  2. oracle取前5条数据,ORACLE查询前五条数据

    以下的文章主要介绍的是如何在Oracle实现 SELECT TOP N的实际操作方法,我们主要是以举例子的方式来引出Oracle实现 SELECT TOP N的具体操作,以下就文章的具体内容的描述,望 ...

  3. oracle 查询每组条数,Oracle SQL查询:根据时间检索每组的最新值

    这是一个完整的,经过测试的例子. CREATE TABLE tbl1 (ID NUMBER, dt DATE, quantity NUMBER); DELETE FROM tbl1; insert i ...

  4. oracle查询最高一条记录,oracle 查询已有记录,上一条记录,下一条记录

    oracle可以使用 lead.lag  函数来查询已有记录的下一条.上一条记录. 表结构如下: 如要查询Staffno是6-1102的前一条记录 select * from staff where ...

  5. oracle常用插入一条语句,Oracle:用一条 INSERT 语句批量插入多条记录

    用一条 INSERT 语句批量插入多条记录,实例如下: 先建立这样一个表 T: SQL> DESC T Name                       Null?    Type ---- ...

  6. oracle获取100条之后的数据,oracle获取前50条数据

    oracle取前几条数据语句 sqlserver中可以用top n 的方法,oracle中用 rownum,但如果只用 rownum会随机取数据,如果想按一定顺序取前几条数据 则可这样写: selec ...

  7. oracle mysql limit用法_mysql以及oracle数据分页的sql示例(limit和Rownum的用法) | Soo Smart!...

    对数据查询结果集截断获取,来实现数据库层的分页.在mysql以及Oracle下的实现如下: MySQL下使用limit和offset,Oracle使用Rownum. MySQL下limit和offse ...

  8. 使用Java和XSLT的10条技巧 (转)

    使用Java和XSLT的10条技巧 这篇文章从书中选出了我认为非常重要的10条技巧.但实际上这有限的10条只是粗略的描述了什么是可能的.其中大多数都集中在Java和XSLT的组合上,而不是在XSLT( ...

  9. SQL查询前10条记录(SqlServer/mysql/oracle)[语法分析]

    Sql Server : Sql代码 select top X * from table_name --查询前X条记录,可以改成需要的数字. select top n * from (select t ...

最新文章

  1. 解读ADC采样芯片(EV10AQ190A)的工作模式(单通道模式)
  2. 蓝桥杯-区间k大数查询(java)
  3. id、构造方法、Category 分类、类的本质、description方法、SEL
  4. 最新进展!单细胞数据显示ACE2在鼻腔、肾脏、睾丸均有分布!
  5. c语言延时函数delay延时一秒_IMX6UL裸机实现C语言LED实验
  6. PHP学习笔记【9】_表达式
  7. map 值为指针_Go sync.Map 并发效率为什么那么高?
  8. stm32f103c8t6 AD DMA连续采集8个通道
  9. android go解析json,Go 关于Json通用解析
  10. T SQL + 正则表达式
  11. python中argsort_numpy的argsort函数
  12. 职场中混日子的人都有这几种习惯
  13. 目标检测算法 2020_One-stage目标检测算法综述
  14. Win10如何安装自带的XPS Viewer查看器
  15. vue中的混入mix
  16. unity2D:视觉差Parallex
  17. Python获取法定节假日
  18. 迪士尼机器人芭蕾舞_迪士尼公园只有卡通公主?内含大量惊人科技感机器人
  19. 检测网络是否稳定的计算机命令,电脑中常用的网络检测命令|电脑中检测网络是否存在故障的几条命令...
  20. phpstudy打不开localhost【已解决】

热门文章

  1. 成就高效DevOps团队的“降龙十八掌”第一式——codeReview?
  2. H5地理位置信息、微信摇一摇
  3. DB2如何停库/如何使数据库处于offline状态
  4. Android 图片内存占用过大?不存在的...
  5. 学校智慧照明系统的应用意义
  6. Python RSA 加密解密
  7. ChIP-seq和RNA-seq联合分析助力揭示暹罗炭疽菌对咯菌腈反应的作用
  8. oracle redo重做,oracle redo 重做日志文件
  9. Win2000/XP故障恢复控制台主要命令
  10. VS2015(Install Shield 2015 )打包教程。集成第三方驱动。修改安装包图标、安装风格。