假定要进行索引的文本语言是数据库设置中所指定的语言。使用数据库设置中所指定语言的默认非索引字表。非索引字表可标识系统在索引过程中忽略的单词(非索引字)。如果可用,启用语言的模糊查询和词干查询功能。当然,通过创建自己的首选项,并在创建索引时指定这些自定义首选项,可以更改默认的索引行为。
如果可用,启用语言的模糊查询和词干查询功能。
3.索引维护
应用程序在基表中插入、更新或删除文档后,需要进行索引维护。如果基表为静态(即初始化索引后,未对文档进行更新、插入或删除操作),则无需维护索引。但是,如果在基表上执行DML(插入、更新或删除)操作,则必须更新索引。可以使用ALTER INDEX手动同步索引。还可以在后台运ctxsrv服务器,该服务器会对索引进行定期自动同步。
4.发出查询
使用SELECT语句中的CONTAINS运算符发出文本查询。使用CONTAINS可以进行两种查询:词查询和ABOUT查询。词查询是对输入到CONTAINS运算符中单引号间的精确单词或短语的查询;ABOUT查询增加了某查询所返回的相关文档的数目。在英语中,ABOUT查询可以使用索引的主题词组件,这样,运算符将根据查询的概念返回文档,而不是仅依据所指定的精确单词或短语。
5.显示满足查询条件的文档
通常,通过使用Oracle Text查询应用程序,用户可查看查询所返回的文档。用户从命中列表中选择一个文档,然后应用程序以某种形式显示该文档。通过Oracle Text,可以用不同的方式再现文档。例如,可以通过突出显示查询词来显示文档。突出显示的查询词可以是相关词查询中的词,也可以是英文ABOUT查询中的主题词。
5.2.3Oracle Text的搜索示例
现在,举一个例子来说明上面介绍的搜索流程。
1.装载文本
首先,使用scott用户登录SQL Plus Sheet。
在SQL Plus Sheet中输入如下语句,建立测试表test。
create table test
(
id number,
title varchar2(30),
body varchar2(1000)
);
现在,输入若干测试数据,可以运行如下SQL语句:
A insert into test values(1,"关系型数据库管理软件",′虽然早在1970年就诞生了关系模型理论,但是市场上迟迟不见关系型数据库管理软件的推出。主要原因是很多反对者认为关系型数据库速度太慢,比不上当时的层次式数据库。而IBM虽然1973年就启动了System R的项目来研究关系型数据库的实际可行性,却也没有及时推出这样的产品,因为当时IBM的IMS(着名的层次型数据库)市场不错,如果推出关系型数据库,牵涉到IBM很多人的自身利益。");
insert into test values(2,"计算机公司",′1977年6月,Larry Ellison与Bob Miner和Ed Oates在硅谷共同创办了一家名为软件开发实验室(SoftwareDevelopment Laboratories,SDL)的计算机公司(Oracle公司的前身)。那个时候,32岁的Larry Ellison,这个读了三家大学都没能毕业的辍学学生,还只是一个普通的软件工程师。公司创立之初,Miner是总裁,Oates为副总裁,而Ellison,因为一个合同的事情,还在另一家公司上班。");
insert into test values(3,′Bruce Scott","没多久,第一位员工Bruce Scott(用过Oracle数据库软件的人都知道有个Scott用户的吧?没错,就是这个Scott,至于Scott用户的密码 Tiger,那是Scott养的猫的名字)加盟进来,在Miner和Oates有些厌倦了那种合同式的开发工作后,他们决定开发通用软件,不过他们还不知道自己能开发出来什么样的产品。");
insert into test values(4,"Ellison和Miner预见",′在Miner和Oates有些厌倦了那种合同式的开发工作后,他们决定开发通用软件,不过他们还不知道自己能开发出来什么样的产品。Oates最先看到了埃德加·考特的那篇着名的论文连同其他几篇相关的文章并推荐Ellison和Miner也阅读一下。Ellison和Miner预见到数据库软件的巨大潜力,于是,SDL开始策划构建可商用的关系型数据库管理系统(RDBMS)。");
insert into test values(5,"关系软件有限公司","Oracle(字典里的解释有“神谕,预言”之意)是一切智慧的源泉。1979年,SDL更名为关系软件有限公司(Relational Software,Inc.,RSI)");insert into test values(6,"美国中央情报局",′虽然软件不是很好,但客户还是有的。美国中央情报局迫不及待地想买一套这样的软件来满足他们的需求。但在咨询了IBM公司之后发现IBM没有可以商用的产品,他们联系了RSI。于是RSI有了第一个客户。");
提交事务,运行commit语句,将数据提交。
可以从Enterprise Manager Console查看到表格已经建立好,数据已经写入。
2.为文本建立索引
文本装入文本列后,可以创建Oracle Text索引。Oracle Text索引有CONTEXT、CTXCAT、CTXRULE三种,这三种索引的搜索函数分别为contains、catsearch和matches。CONTEXT索引一般是应用于比较大/长的文本查询;CTXCAT索引一般是应用于多字段的文本查询,它的查询性能比CONTEXT要好,且CTXCAT索引是事务性的,执行DML后数据库会自动同步索引,不像CONTEXT要用到ctx ddl.sync index同步。这里建立CONTEXT索引。
输入如下SQL语句,建立名为test ctx idx的索引,全文搜索作用于body列,全文索引的类型是CONTEXT。
create index test ctx idx
on test(body)
indextype is ctxsys.context;
commit;
创建索引后,表DR $ TESTCTX IDX $ I。双击打开,可以看到表的记录被拆分成很多部分进行存储。
注意:索引创建后,如果再向表插入记录,此记录将不会被拆分存储在DR $ TESTCTXIDX $ I表中,即这些后来插入的记录不会被搜索函数contains查询出来的,要查询到这些数据,必须同步索引(ctx ddl.sync index)或重建索引(alter index..rebuild)。
3.发出查询
现在,可以对刚刚建立索引的数据执行全文搜索,分别来看CONTAINS和ABOUT两种搜索方法。
(1)CONTAINS搜索
Oracle全文搜索的CONTAINS语法与SQL Server是非常相似的。但是要注意,语句中的>0部分是有效的OracleSQL所必需的,OracleSQL不支持函数的布尔返回值。
查找含“神谕”的记录,使用如下SQL语句:
select id,title from test where contains(body,"神谕")>0;
查找含“埃及法老”的记录,使用如下SQL语句:
select id,title from test where contains(body,′"埃及法老"")>0;
由于数据库中不含有与“埃及法老”有关的内容,所以搜索结果是“未选定行”。
Oracle全文搜索支持一些表示逻辑关系的符号,例如“AND”,“OR”等。用法与SQLServer类似。比如,查找同时含有“oracle”和“RSI”的记录,使用如下SQL语句:
select id,title from test where contains(body,′"RSI"and"oracle"")>0;
查找同时含有“oracle”或“SCOTT”的记录,使用如下SQL语句:
select id,title from test where contains(body,′"SCOTT"or"oracle"")>0;
现在,查找含有“智慧”的记录,使用如下SQL语句:
select id,title from test where contains(body,′"智慧"")>0;
发现得不到结果。难道是因为数据库中没有这样的记录吗?
运行下面这条语句:
select id from test where instr(body,"智慧")>0;
这是用常规的搜索方式进行查询,这说明数据库中存在含“智慧”的记录。
类似地,可以运行以下语句进行模糊查询:
select id from test where body like"%智慧%";
这也说明数据库中存在含“智慧”的记录。
现在,尝试运行如下语句进行全文搜索:
select id,title from test where contains(body,′"是一切智慧的源泉"")>0;
为什么会出现这样的结果呢?
进入Enterprise ManagerConsole,查看scott用户的DR $ test ctx idx $ I表,可以在TOKEN TEXT列发现“是一切智慧的源泉”这个词,但是,没有“智慧”这条记录。其实,Oracle的全文搜索,就是首先将文本进行分词,然后按照分词的TOKEN TEXT进行检索的。这也正是前面讲的倒排索引的一个具体而明显的应用。
fuzzy()函数可以用于模糊搜索,比如:用fuzzy()模糊查找含“oracla”的记录,允许错一个字母,输入如下语句:
select id,title from test where contains(body,"fuzzy("oracla")")>0;
在数据库中其实并不含有“oracla”,但是,使用了fuzzy搜索之后,所有含有“oracle”的记录都被查询出来了。
可以使用SCORE函数来限定搜索结果的分值,以此来过滤搜索结果。例如:查找文本列中包含oracle一词的所有文档。每行的分值由使用标签1的SCORE运算符限定,运行下面的语句:
select score(1)id from test where contains(body,"oracle",1)>0;
(2)ABOUT搜索
以下查询语句将查找文本列中关于主题“oracle”的所有文档,而不是仅包“oracle”一词的文档:
select score(1)id from test where contains(body,"about(oracle)′,1)>0;
4.索引维护
索引建好后,如果表中的数据发生变化,比如增加或修改了记录,怎么办?由于对表所发生的任何DML语句,都不会自动修改索引,因此,必须定时同步(synchronize)和优化(optimize)索引,以正确反映数据的变化。
同步可以使用下面的语句:
ALTER INDEX test ctx idx REBUILD PARAMETERS("resume memory20M");
这条语句中限定了使用20MB内存。也可以直接用alter index testctx idx rebuild;语句进行同步。
5.索引删除
删除索引,可使用如下语句:
drop index test ctx idx;
或者采用5.2.4节介绍的可视化操作方法,只需要在索引节点处,利用右键菜单进行操作即可。
5.2.4可视化创建索引
前面讲述了使用SQL语句来操作全文索引的方法,这一节介绍所见即所得的可视化方式来操纵索引。
首先,建立测试数据库,并输入测试数据。
在SQL Plus Sheet中输入如下语句,建立测试表格tianen并插入若干测试数据。
create table tianen
(
id number,
title varchar2(30),
body varchar2(1000)
);
insert into tianen values(1,"关系型数据库管理软件",′虽然早在1970年就诞生了关系模型理论,但是市场上迟迟不见关系型数据库管理软件的推出。主要原因是很多反对者认为关系型数据库速度太慢,比不上当时的层次式数据库。而IBM虽然1973年就启动了System R的项目来研究关系型数据库的实际可行性,却也没有及时推出这样的产品,因为当时IBM的的IMS(着名的层次型数据库)市场不错,如果推出关系型数据库,牵涉到IBM很多人的自身利益。");