oracle全文索引之SECTION GROUP

来源:互联网 发布:网络热词英语的研究 编辑:程序博客网 时间:2024/04/29 05:11

这篇文章介绍Oracle全文索引的SECTION GROUP属性中的NULL_SECTION_GROUP。
Oracle的全文索引的SECTION GROUP属性用来支持包含内部结构的文档,比如HTML、XML文档等。使用了SECTION GROUP属性,可以在查询文档的时候指定在文档的哪一部分进行查询。可以将查询范围限定在标题中。

这篇文章首先介绍最简单的NULL_SECTION_GROUP,如果DATASTORE的属性没有设置为URL_DATASTORE且FILTER的属性没有设置为INSO_FILTER,则NULL_SECTION_GROUP就是默认的SECTION_GROUP,否则HTML_SECTION_GROUP为默认SECTION_GROUP。NULL_SECTION_GROUP的含义从名称上已经可以看出,就是没有设置SECTIONGROUP,但Oracle还是提供了两个预定义的SECTION:SENTENCE和PARAGRAPH。下面简单介绍NULL_SECTION_GROUP,并说明SENTENCE和PARAGRAPH的设置和使用。

SQL> conn myuser/myuser
Connected.
SQL> CREATE TABLE T (ID NUMBER, DOCS VARCHAR2(100));

Table created.

SQL> INSERT INTO T VALUES (1, 'A SIMPLE EXAMPLE FOR SECTION GROUP, TEST NULL_SECTION_GROUPATTRIBUTE.');

1 row created.

SQL> INSERT INTO T VALUES (2, 'THIS RECORD ONE, CAN BE QUERY IN NORNAL');

1 row created.

SQL> INSERT INTO T VALUES (3, 'THIS RECORD CAN BE QUERY IN SENTERNCE.');

1 row created.

SQL> INSERT INTO T VALUES (4, 'THIS RECORD
2 ARE TESTED FOR
3 THE QUERY IN PARAGRAPH');

1 row created.

SQL> COMMIT;

Commit complete.


SQL> CREATE INDEX IND_T_DOCS ON T(DOCS) INDEXTYPE IS CTXSYS.CONTEXT
2 PARAMETERS ('SECTION GROUP CTXSYS.NULL_SECTION_GROUP');

Index created.

建立一个NULL_SECTION_GROUP属性的索引很简单,而且NULL_SECTION_GROUP不启用节搜索,因此查询上也没有什么特殊的东西。但是NULL_SECTION_GROUP可以支持Oracle预定义的两种节搜索,SENTENCE和PARAGRAPH,下面就简单说明一下这两个特性:

SQL> column docs format a50

SQL> SELECT * FROM T WHERE CONTAINS(DOCS, 'RECORD AND QUERY') > 0;

ID DOCS
---------- --------------------------------------------------
2 THIS RECORD ONE, CAN BE QUERY IN NORNAL
3 THIS RECORD CAN BE QUERY IN SENTERNCE.
4 THIS RECORD
ARE TESTED FOR
THE QUERY IN PARAGRAPH

SQL> SELECT * FROM T WHERE CONTAINS(DOCS, '(RECORD AND QUERY) WITHIN SENTENCE') > 0;
SELECT * FROM T WHERE CONTAINS(DOCS, '(RECORD AND QUERY) WITHIN SENTENCE') > 0
*
ERROR at line 1:
ORA-29902: error in executing ODCIIndexStart() routine
ORA-20000: Oracle Text error:
DRG-10837: section SENTENCE does not exist


SQL> SELECT * FROM T WHERE CONTAINS(DOCS, '(RECORD AND QUERY) WITHIN PARAGRAPH') > 0;
SELECT * FROM T WHERE CONTAINS(DOCS, '(RECORD AND QUERY) WITHIN PARAGRAPH') > 0
*
ERROR at line 1:
ORA-29902: error in executing ODCIIndexStart() routine
ORA-20000: Oracle Text error:
DRG-10837: section PARAGRAPH does not exist

在默认情况下,没有设置这两个节,因此相应的查询语法会报错:

SQL> DROP INDEX IND_T_DOCS;

Index dropped.


SQL> BEGIN
2 CTX_DDL.CREATE_SECTION_GROUP('TEST_NULL', 'NULL_SECTION_GROUP');
3 CTX_DDL.ADD_SPECIAL_SECTION('TEST_NULL', 'SENTENCE');
4 CTX_DDL.ADD_SPECIAL_SECTION('TEST_NULL', 'PARAGRAPH');
5 END;
6 /

SQL> CREATE INDEX IND_T_DOCS ON T(DOCS) INDEXTYPE IS CTXSYS.CONTEXT
2 PARAMETERS ('SECTION GROUP TEST_NULL');

Index created.

SQL> SELECT * FROM T WHERE CONTAINS(DOCS, 'RECORD AND QUERY') > 0;

ID DOCS
---------- --------------------------------------------------
2 THIS RECORD ONE, CAN BE QUERY IN NORNAL
3 THIS RECORD CAN BE QUERY IN SENTERNCE.
4 THIS RECORD
ARE TESTED FOR
THE QUERY IN PARAGRAPH


SQL> SELECT * FROM T WHERE CONTAINS(DOCS, '(RECORD AND QUERY) WITHIN SENTENCE') > 0;

ID DOCS
---------- --------------------------------------------------
2 THIS RECORD ONE, CAN BE QUERY IN NORNAL
3 THIS RECORD CAN BE QUERY IN SENTERNCE.
4 THIS RECORD
ARE TESTED FOR
THE QUERY IN PARAGRAPH


SQL> SELECT * FROM T WHERE CONTAINS(DOCS, '(RECORD AND QUERY) WITHIN PARAGRAPH') > 0;

ID DOCS
---------- --------------------------------------------------
2 THIS RECORD ONE, CAN BE QUERY IN NORNAL
3 THIS RECORD CAN BE QUERY IN SENTERNCE.
4 THIS RECORD
ARE TESTED FOR
THE QUERY IN PARAGRAPH

通过在自定义SECTION GROUP TEST_NULL中设置SENTENCE和PARAGRAPH,使得查询中的节搜索语法顺利执行。但是查询的结果却和我预想的有很大的出入。
这是由于SENTENCE和PARAGRAPH是Oracle预定义的节组,节组预定义的规则完全由FILTER参数控制。因此,不同格式的文章甚至是相同格式不同语言的文档的节属性也都不相同。

经过一系列的测试发现,中文WORD文档的SENTENCE和PARAGRAPH节搜索还是比较好理解的,下面通过一个简单的例子进行说明。

首先,重建测试用表:

SQL> DROP TABLE T;

表已丢弃。

SQL> CREATE TABLE T (ID NUMBER, DOCS VARCHAR2(100));

表已创建。

SQL> INSERT INTO T VALUES (1, 'TEST.DOC');

已创建 1 行。

SQL> COMMIT;

提交完成。

SQL> CONN CTXSYS/CTXSYS@YANGTK
已连接。
SQL> BEGIN
2 CTX_DDL.CREATE_PREFERENCE('TEST_FILE', 'FILE_DATASTORE');
3 CTX_DDL.SET_ATTRIBUTE('TEST_FILE', 'PATH', 'F:');
4 CTX_DDL.CREATE_PREFERENCE('TEST_CHINESE_VGRAM_LEXER', 'CHINESE_VGRAM_LEXER');
5 END;
6 /

PL/SQL 过程已成功完成。

SQL> CONN YANGTK/YANGTK@YANGTK
已连接。
SQL> CREATE INDEX IND_T_DOCS ON T(DOCS) INDEXTYPE IS CTXSYS.CONTEXT
2 PARAMETERS ('DATASTORE CTXSYS.TEST_FILE FILTER CTXSYS.INSO_FILTER
3 LEXER CTXSYS.TEST_CHINESE_VGRAM_LEXER SECTION GROUP CTXSYS.TEST_NULL');

索引已创建。

索引建立好了,在查询之前,首先看一下被索引文档TEST.DOC的内容:

--------------------------------------------------------------------------------------------------

这个例子

可以被

行节查询到。

上面的内容和当前的内容,都可以被段节访问到。

--------------------------------------------------------------------------------------------------

上面两条分隔线之间的内容就是被索引的文档。Oracle认为中文的WORD文档中前三行记录属于一个SENTENCE,里面的内容可以被SENTENCE节搜索查询到。而上面的三行和最后的一行中的内容只能通过PARAGRAPH节搜索查询到。

SQL> SELECT * FROM T WHERE CONTAINS(DOCS, '例子 AND 查询') > 0;

ID DOCS
---------- ------------------------------
1 TEST.DOC

SQL> SELECT * FROM T WHERE CONTAINS(DOCS, '(例子 AND 查询) WITHIN SENTENCE') > 0;

ID DOCS
---------- ------------------------------
1 TEST.DOC

SQL> SELECT * FROM T WHERE CONTAINS(DOCS, '(例子 AND 查询) WITHIN PARAGRAPH') > 0;

ID DOCS
---------- ------------------------------
1 TEST.DOC

SQL> SELECT * FROM T WHERE CONTAINS(DOCS, '例子 AND 访问') > 0;

ID DOCS
---------- ------------------------------
1 TEST.DOC

SQL> SELECT * FROM T WHERE CONTAINS(DOCS, '(例子 AND 访问) WITHIN SENTENCE') > 0;

未选定行

SQL> SELECT * FROM T WHERE CONTAINS(DOCS, '(例子 AND 访问) WITHIN PARAGRAPH') > 0;

ID DOCS
---------- ------------------------------
1 TEST.DOC

 

 

这篇文章介绍Oracle全文索引的SECTION GROUP属性中的BASIC_SECTION_GROUP。
NULL_SECTION_GROUP其实并不真正支持节搜索,而在支持节搜索的SECTION_GROUP中,BASIC_SECTION_GROUP是最基础的一种属性,它只支持以<tag>开头以</tag>结尾的结构的文档。这篇文章在介绍BASIC_SECTION_GROUP的同时,简单介绍一下节搜索。

SQL> CREATE TABLE T (ID NUMBER, DOCS VARCHAR2(1000));

Table created.

SQL> INSERT INTO T VALUES (1, '<HEADING>TITLE</HEADING>
2 <CONTEXT>This is the contents of the example.
3 Use this example to test the basic_section_group.</CONTEXT>');

1 row created.

SQL> INSERT INTO T VALUES (2, '<HEADING>EXAMPLE</HEADING>
2 <CONTEXT>This line incluing the word title too.</CONTEXT>');

1 row created.

SQL> COMMIT;

Commit complete.

SQL> CREATE INDEX IND_T_DOCS ON T(DOCS) INDEXTYPE IS CTXSYS.CONTEXT;

Index created.

SQL> SELECT ID FROM T WHERE CONTAINS (DOCS, 'HEADING') > 0;

ID
----------
1
2

在HTML、XML等类似结构的文档中,除了用来显示的内容外,还包括了大量用于控制结构的标识,而这些标识可能是不希望被索引的,而这就是SECTION GROUP其中的一个主要功能。

在上面的例子中,默认情况(NULL_SECTION_GROUP)肯定会将HEADING放入到索引键值中,但如果建立了BASIC_SECTION_GROUP则在

查询文档的时候,HEADING、CONTEXT等标签内容将不再被索引

SQL> DROP INDEX IND_T_DOCS;

Index dropped.

SQL> exec CTX_DDL.CREATE_SECTION_GROUP('TEST_BASIC', 'BASIC_SECTION_GROUP');

PL/SQL procedure successfully completed.

SQL> CREATE INDEX IND_T_DOCS ON T(DOCS) INDEXTYPE IS CTXSYS.CONTEXT
2 PARAMETERS ('SECTION GROUP TEST_BASIC');

Index created.

SQL> SELECT ID FROM T WHERE CONTAINS (DOCS, 'HEADING') > 0;

no rows selected

SQL> SELECT ID FROM T WHERE CONTAINS (DOCS, 'USE') > 0;

ID
----------
1


节搜索的另一个主要功能就是可以限制查询的范围。如果上面的例子中,文档包含了两部分,标题和正文,其中标题使用标签

<HEADING>和<HEADING>,正文使用标签<CONTEXT>和<CONTEXT>。因此,可以对BASIC_SECTION_GROUP添加区域属性,运行查询在文档的某个范围内进行。

SQL> DROP INDEX IND_T_DOCS;

Index dropped.

SQL> exec CTX_DDL.ADD_ZONE_SECTION('TEST_BASIC', 'HEAD', 'HEADING');

PL/SQL procedure successfully completed.

SQL> CREATE INDEX IND_T_DOCS ON T(DOCS) INDEXTYPE IS CTXSYS.CONTEXT
2 PARAMETERS ('SECTION GROUP TEST_BASIC');

Index created.

SQL> SELECT ID FROM T WHERE CONTAINS (DOCS, 'TITLE') > 0;

ID
----------
1
2

SQL> SELECT ID FROM T WHERE CONTAINS (DOCS, 'TITLE WITHIN HEAD') > 0;

ID
----------
1

 

 

这篇文章介绍Oracle全文索引的SECTION GROUP属性中的HTML_SECTION_GROUP。

虽然BASIC_SECTION_GROUP已经可以解决很多基本的节搜索问题,但是Oracle还是推荐对于HTML文档使用专门定义的HTML_SECTION_GROUP属性。这是由于HTML文档具有很多不规范的表示方法,使用HTML_SECTION_GROUP能够更好的识别HTML文档的机构。另外,BASIC_SECTION_GROUP不支持不匹配的括号、注释表示和属性等。

下面通过一个简单的例子来看一下HTML_SECTION_GROUP和BASIC_SECTION_GROUP的区别。HTML_SECTION_GROUP支持META标签中的NAME/CONTENT属性对的查询,下面看具体的例子。

SQL> CREATE TABLE T (ID NUMBER, DOCS VARCHAR2(1000));

表已创建。

SQL> INSERT INTO T VALUES (1, 'README.HTML');

已创建 1 行。

SQL> COMMIT;

提交完成。

SQL> CONN CTXSYS/CTXSYS@YANGTK
已连接。
SQL> BEGIN
2 CTX_DDL.CREATE_PREFERENCE('TEST_FILE', 'FILE_DATASTORE');
3 CTX_DDL.SET_ATTRIBUTE('TEST_FILE', 'PATH', 'F:');
4 CTX_DDL.CREATE_SECTION_GROUP('TEST_BASIC', 'BASIC_SECTION_GROUP');
5 CTX_DDL.ADD_FIELD_SECTION('TEST_BASIC', 'MTAG', 'META@HTML');
6 CTX_DDL.CREATE_SECTION_GROUP('TEST_HTML', 'HTML_SECTION_GROUP');
7 CTX_DDL.ADD_FIELD_SECTION('TEST_HTML', 'MTAG', 'META@HTML');
8 END;
9 /

PL/SQL 过程已成功完成。

下面看一下README.HTML文档的内容:

<HTML>
<HEAD>
<TITLE>Oracle Ultra Search Sample Crawler Agent Readme</TITLE>
<META NAME="HTML" CONTENT="SECTION GROUP">
</HEAD>
<BODY bgcolor="#FFFFFF">
<h1>Oracle Ultra Search Sample Crawler Agent Readme</h1>
<H2>Table of Contents</H2>
<blockquote> <A REL="CHAPTER" HREF="#CHP1">1. Introduction</A>
<A REL="CHAPTER" HREF="#CHP2">2. Sample agent files</A>
<A REL="CHAPTER" HREF="#CHP3">3. Setting up the Sample Crawler Agent</A>
</blockquote>
<H2><A NAME="CHP1"></A>1. Introduction</H2>
<blockquote>
<p>Oracle Ultra Search provides a sample implementation of user defined data source
agent which uses the Ultra Search agent API. The purpose of this sample is to
provide a concrete illustration on the usage of the agent APIs.
<p>Upon invocation this sample agent connects to a specified Oracle database and
retrieve the contents of a table for the crawler to collect and index.
<p>The sample agent are fully functional and can be customized to adapt to other
database based data source. This agent performs the following task:</p>
<ul>
<li>Reading of data source parameters </li>
<li>Connection to the database that contains the data source </li>
<li>Initialization of fetching document URL and attributes from the data source </li>
<li>Fetching of document URL and attributes from the data source </li>
<li>Disconnection from the data source </li>
</ul>
<p>Complete and comprehensive documentation on agent API is provided in the following
document:</p>
<ul>
<li>Ultra Search Crawler agent API </li>
</ul>
</blockquote>
</BODY>
</HTML>

观察上面的META标签,里面包含NAME/CONTENT属性对,可以根据例子的方式,基于META中名称的值建立FIELD,来搜索CONTENT的值。

SQL> CONN YANGTK/YANGTK@YANGTK
已连接。
SQL> CREATE INDEX IND_T_DOCS ON T(DOCS) INDEXTYPE IS CTXSYS.CONTEXT
2 PARAMETERS('DATASTORE CTXSYS.TEST_FILE FILTER CTXSYS.NULL_FILTER
3 SECTION GROUP CTXSYS.TEST_BASIC');

索引已创建。

SQL> SELECT * FROM T WHERE CONTAINS(DOCS, 'DATABASE') > 0;

ID DOCS
---------- ----------------------------------------
1 README.HTML

SQL> SELECT * FROM T WHERE CONTAINS(DOCS, 'SECTION WITHIN MTAG') > 0;

未选定行

SQL> DROP INDEX IND_T_DOCS;

索引已丢弃。

SQL> CREATE INDEX IND_T_DOCS ON T(DOCS) INDEXTYPE IS CTXSYS.CONTEXT
2 PARAMETERS('DATASTORE CTXSYS.TEST_FILE FILTER CTXSYS.NULL_FILTER
3 SECTION GROUP CTXSYS.TEST_HTML');

索引已创建。

SQL> SELECT * FROM T WHERE CONTAINS(DOCS, 'DATABASE') > 0;

ID DOCS
---------- ----------------------------------------
1 README.HTML

SQL> SELECT * FROM T WHERE CONTAINS(DOCS, 'SECTION WITHIN MTAG') > 0;

ID DOCS
---------- ----------------------------------------
1 README.HTML

从这个例子可以看出,对于HTML文档来说,使用HTML_SECTION_GROUP可以拥有更多的功能。

最后提醒一下,无论是FIELD_SECTION还是ZONE_SECTION,表示文档的TAG标签都是大小写敏感的,其大小写需要和原文中匹配。

 


这篇文章介绍Oracle全文索引的SECTION GROUP属性中的XML_SECTION_GROUP。

Oracle对HTML文档预定义了专门的HTML_SECTION_GROUP,而对XML文档,也预定义好了专门的SECTION_GROUP——XML_SECTION_GROUP。

其实,Oracle除了XML_SECTION_GROUP外,AUTO_SECTION_GROUP和PATH_SECTION_GROUP也都是为XML文档预定义的,不过,这篇文档先只讨论XML_SECTION_GROUP。

XML文档的格式要求比HTML文档严谨、规范,这也使得XML_SECTION_GROUP比HTML_SECTION_GROUP增加了新的功能,比如ATTRIBUTE的搜索。

如果一篇结构类型下面例子中的文档,使用HTML_SCTION_GROUP和BASIC_SECTION_GROUP都是无法索引到内容的,只能通过XML_SECTION_GROUP的ATTR_SECTION来检索标签属性中的内容。

文档内容如下:

<?xml version="1.0" standalone="yes" ?>
<!-- Copyright (c) 2001 Oracle Corporation. All rights Reserved -->
<!-- Do not modify the contents of this file by hand. -->
<COMP_CONTEXT>
<VAR_LIST SIZE="0">
<VAR NAME="PROD_HOME" TYPE="String" DESC_RES_ID="" SECURE="F"VAL="F:oracleoracle920oracle_java_jdbc_jdbc_common" ADV="F"/>
</VAR_LIST>
<CONST_LIST SIZE="10">
<CONST NAME="Minimal" PLAT_SP="F" TYPE="String" TRANS="T" VAL="Minimal_ALL"/>
<CONST NAME="COMPONENT_DESC" PLAT_SP="F" TYPE="String" TRANS="T" VAL="COMPONENT_DESC_ALL"/>
<CONST NAME="Custom_DESC" PLAT_SP="F" TYPE="String" TRANS="T" VAL="Custom_DESC_ALL"/>
<CONST NAME="Typical_DESC" PLAT_SP="F" TYPE="String" TRANS="T" VAL="Typical_DESC_ALL"/>
<CONST NAME="Complete" PLAT_SP="F" TYPE="String" TRANS="T" VAL="Complete_ALL"/>
<CONST NAME="Custom" PLAT_SP="F" TYPE="String" TRANS="T" VAL="Custom_ALL"/>
<CONST NAME="COMPONENT_NAME" PLAT_SP="F" TYPE="String" TRANS="F" VAL="JDBC Common Files"/>
<CONST NAME="Minimal_DESC" PLAT_SP="F" TYPE="String" TRANS="T" VAL="Minimal_DESC_ALL"/>
<CONST NAME="Typical" PLAT_SP="F" TYPE="String" TRANS="T" VAL="Typical_ALL"/>
<CONST NAME="Complete_DESC" PLAT_SP="F" TYPE="String" TRANS="T" VAL="Complete_DESC_ALL"/>
</CONST_LIST>
</COMP_CONTEXT>

如果建立不同的HTML_SECTION_GROUP或XML_SECTION_GROUP是检索不到内容的:

SQL> CREATE TABLE T (ID NUMBER, DOCS VARCHAR2(1000));

表已创建。

SQL> INSERT INTO T VALUES (1, 'context.xml');

已创建 1 行。

SQL> COMMIT;

提交完成。

SQL> CONN CTXSYS/CTXSYS@YANGTK
已连接。
SQL> BEGIN
2 CTX_DDL.CREATE_PREFERENCE('TEST_FILE', 'FILE_DATASTORE');
3 CTX_DDL.SET_ATTRIBUTE('TEST_FILE', 'PATH', 'F:');
4 CTX_DDL.CREATE_SECTION_GROUP('TEST_HTML', 'HTML_SECTION_GROUP');
5 CTX_DDL.CREATE_SECTION_GROUP('TEST_XML', 'XML_SECTION_GROUP');
6 END;
7 /

PL/SQL 过程已成功完成。

SQL> CONN YANGTK/YANGTK@YANGTK
已连接。
SQL> CREATE INDEX IND_T_DOCS ON T (DOCS) INDEXTYPE IS CTXSYS.CONTEXT
2 PARAMETERS('DATASTORE CTXSYS.TEST_FILE FILTER CTXSYS.NULL_FILTER
3 SECTION GROUP CTXSYS.TEST_HTML');

索引已创建。

SQL> SELECT * FROM T WHERE CONTAINS (DOCS, 'COMPLETE') > 0;

未选定行

SQL> DROP INDEX IND_T_DOCS;

索引已丢弃。

SQL> CREATE INDEX IND_T_DOCS ON T (DOCS) INDEXTYPE IS CTXSYS.CONTEXT
2 PARAMETERS('DATASTORE CTXSYS.TEST_FILE FILTER CTXSYS.NULL_FILTER
3 SECTION GROUP CTXSYS.TEST_XML');

索引已创建。

SQL> SELECT * FROM T WHERE CONTAINS (DOCS, 'COMPLETE') > 0;

未选定行

SQL> DROP INDEX IND_T_DOCS;

索引已丢弃。

对于XML_SECTION_GROUP可以建立ATTRIBUTE节组:

SQL> CONN CTXSYS/CTXSYS@YANGTK
已连接。
SQL> BEGIN
2 CTX_DDL.ADD_ATTR_SECTION('TEST_HTML', 'NAME', 'CONST@NAME');
3 END;
4 /
BEGIN
*
ERROR 位于第 1 行:
ORA-20000: Oracle Text 错误:
DRG-12225: 这一段类型不能添加到此段组中
ORA-06512: 在"CTXSYS.DRUE", line 157
ORA-06512: 在"CTXSYS.CTX_DDL", line 314
ORA-06512: 在line 2


SQL> BEGIN
2 CTX_DDL.ADD_ATTR_SECTION('TEST_XML', 'NAME', 'CONST@NAME');
3 END;
4 /

PL/SQL 过程已成功完成。

SQL> CONN YANGTK/YANGTK@YANGTK
已连接。
SQL> CREATE INDEX IND_T_DOCS ON T (DOCS) INDEXTYPE IS CTXSYS.CONTEXT
2 PARAMETERS('DATASTORE CTXSYS.TEST_FILE FILTER CTXSYS.NULL_FILTER
3 SECTION GROUP CTXSYS.TEST_XML');

索引已创建。

SQL> SELECT * FROM T WHERE CONTAINS (DOCS, 'COMPLETE WITHIN NAME') > 0;

ID DOCS
---------- ----------------------------------------
1 context.xml

 

 

 

这篇文章介绍Oracle全文索引的SECTION GROUP属性中的AUTO_SECTION_GROUP。


Oracle的AUTO_SECTION_GROUP是XML_SECTION_GROUP的增强型。对于XML_SECTION_GROUP用户需要自己添加需要定义的节组,而使用AUTO_SECTION_GROUP,则Oracle会自动添加节组以及属性信息。

SQL> CREATE TABLE T (ID NUMBER, DOCS VARCHAR2(4000));

表已创建。

SQL> INSERT INTO T VALUES (1, '<!DOCTYPE TargetMetadata SYSTEM "../dtds/TargetMetadata.dtd">
2
3 <TargetMetadata META_VER="1.0" TYPE="oracle_csa_collector">
4 <Display>
5 <Label NLSID="oracle_csa_collector">CSA Collector</Label>
6 </Display>
7
8 <!-- Metric oracle_csa -->
9 <Metric NAME="oracle_csa" TYPE="EXTERNAL" HELP="NO_HELP">
10 <Display>
11 <Label NLSID="oracle_csa">CSA Configuration</Label>
12 </Display>
13 <QueryDescriptor FETCHLET_ID="OS">
14 <Property NAME="emdRoot" SCOPE="SYSTEMGLOBAL">emdRoot</Property>
15 <Property NAME="scriptsDir" SCOPE="SYSTEMGLOBAL">scriptsDir</Property>
16 <Property NAME="targetGUID" SCOPE="INSTANCE">GUID</Property>
17 <Property NAME="command" SCOPE="GLOBAL"><![CDATA[
18 "%perlBin%/perl" "%scriptsDir%/osm/ecmCollectCSA.pl" -emdroot"%emdRoot%" -outfile "%loaderFile%" -targetguid "%targetGUID%" -indir"%recvFileDir%" -emdURL "%emdURL%"
19 ]]>
20 </Property>
21 </QueryDescriptor>
22 </Metric>
23
24 <InstanceProperties>
25 <InstanceProperty NAME="recvFileDir" CREDENTIAL="FALSE" OPTIONAL="FALSE">
26 <Display>
27 <Label NLSID="ora_recvFileDir_iprop">Receive File Directory</Label>
28 <ShortName NLSID="ora_recvFileDir_iprop">Receive File Directory</ShortName>
29 </Display>
30 </InstanceProperty>
31 </InstanceProperties>
32
33 </TargetMetadata>
34 ');

已创建 1 行。

SQL> COMMIT;

提交完成。

SQL> CONN CTXSYS/CTXSYS@YANGTK
已连接。
SQL> BEGIN
2 CTX_DDL.CREATE_SECTION_GROUP('TEST_XML', 'XML_SECTION_GROUP');
3 CTX_DDL.CREATE_SECTION_GROUP('TEST_AUTO', 'AUTO_SECTION_GROUP');
4 END;
5 /

PL/SQL 过程已成功完成。

SQL> CONN YANGTK/YANGTK@YANGTK
已连接。
SQL> CREATE INDEX IND_T_DOCS ON T(DOCS) INDEXTYPE IS CTXSYS.CONTEXT
2 PARAMETERS ('SECTION GROUP CTXSYS.TEST_XML');

索引已创建。

SQL> SELECT ID FROM T WHERE CONTAINS(DOCS, 'CONFIGURATION') > 0;

ID
----------
1

SQL> SELECT ID FROM T WHERE CONTAINS(DOCS, 'FILE WITHIN ShortName') > 0;
SELECT ID FROM T WHERE CONTAINS(DOCS, 'FILE WITHIN ShortName') > 0
*
ERROR 位于第 1 行:
ORA-29902: 执行 ODCIIndexStart() 例行程序中出错
ORA-20000: Oracle Text error:
DRG-10837: 段 ShortName 不存在


SQL> SELECT ID FROM T WHERE CONTAINS(DOCS, 'INSTANCE WITHIN Property@SCOPE') > 0;
SELECT ID FROM T WHERE CONTAINS(DOCS, 'INSTANCE WITHIN Property@SCOPE') > 0
*
ERROR 位于第 1 行:
ORA-29902: 执行 ODCIIndexStart() 例行程序中出错
ORA-20000: Oracle Text error:
DRG-10837: 段 Property@SCOPE 不存在


SQL> DROP INDEX IND_T_DOCS;

索引已丢弃。

SQL> CREATE INDEX IND_T_DOCS ON T(DOCS) INDEXTYPE IS CTXSYS.CONTEXT
2 PARAMETERS ('SECTION GROUP CTXSYS.TEST_AUTO');

索引已创建。

SQL> SELECT ID FROM T WHERE CONTAINS(DOCS, 'CONFIGURATION') > 0;

ID
----------
1

SQL> SELECT ID FROM T WHERE CONTAINS(DOCS, 'FILE WITHIN ShortName') > 0;

ID
----------
1

SQL> SELECT ID FROM T WHERE CONTAINS(DOCS, 'INSTANCE WITHIN Property@SCOPE') > 0;

ID
----------
1

通过上面的例子可以看到二者的区别,如果使用XML_SECTION_GROUP,则用户在进行节搜索的时候,需要使用ADD_ZONE_SECTION、ADD_FIELD_SECTION或ADD_ATTR_SECTION来自己添加感兴趣的节组,而使用AUTO_SECTION_GROUP,则Oracle会预定义好所有的节组和属性。

使用AUTO_SECTION_GROUP则不能在调用上面三种添加节组的过程,但是可以使用ADD_STOP_SECTION过程,来控制那些部分不能被节搜索访问到。

SQL> CONN CTXSYS/CTXSYS@YANGTK
已连接。
SQL> BEGIN
2 CTX_DDL.ADD_STOP_SECTION('TEST_AUTO', 'ShortName');
3 END;
4 /

PL/SQL 过程已成功完成。

SQL> CONN YANGTK/YANGTK@YANGTK
已连接。
SQL> ALTER INDEX IND_T_DOCS REBUILD PARAMETERS ('REPLACE SECTION GROUP CTXSYS.TEST_AUTO');

索引已更改。

SQL> SELECT ID FROM T WHERE CONTAINS(DOCS, 'FILE') > 0;

ID
----------
1

SQL> SELECT ID FROM T WHERE CONTAINS(DOCS, 'FILE WITHIN Label') > 0;

ID
----------
1

SQL> SELECT ID FROM T WHERE CONTAINS(DOCS, 'FILE WITHIN ShortName') > 0;

未选定行

指定了STOP_SECTION,仅仅意味着在指定的节组中搜索不到,而在整个文档中,该节组中的内容仍然可见。

另外,需要注意,节组的标识是大小写敏感的。

如果一篇文档大部分的内容都有使用节搜索,那么使用AUTO_SECTION_GROUP属性会相当的方便,但如果一篇文档如果仅仅个别的部分需要使用节搜索,可以考虑使用XML_SECTION_GROUP,并人为的添加个别的SECTION GROUP,这样可以提高索引的创建效率。

 

这篇文章介绍Oracle全文索引的SECTION GROUP属性中的PATH_SECTION_GROUP。

PATH_SECTION_GROUP的功能和AUTO_SECTION_GROUP十分类似,PATH_SECTION_GROUP比AUTO_SECTION_GROUP增加了HASPATH和INPATH操作,但是PATH_SECTION_GROUP不支持ADD_STOP_SECTION属性。

下面通过一个例子简单描述一下PATH_SECTION_GROUP以及HASPATH和INPATH功能。

SQL> CREATE TABLE T (ID NUMBER, DOCS VARCHAR2(1000));

表已创建。

SQL> INSERT INTO T VALUES (1, '<!DOCTYPE TargetMetadata SYSTEM "../dtds/TargetMetadata.dtd">
2
3 <TargetMetadata META_VER="1.0" TYPE="oracle_csa_collector">
4 <Display>
5 <Label NLSID="oracle_csa_collector">CSA Collector</Label>
6 </Display>
7
8 <InstanceProperties>
9 <InstanceProperty NAME="recvFileDir" CREDENTIAL="FALSE" OPTIONAL="FALSE">
10 <Display>
11 <Label NLSID="ora_recvFileDir_iprop">Receive File Directory</Label>
12 <ShortName NLSID="ora_recvFileDir_iprop">Receive File Directory</ShortName>
13 </Display>
14 </InstanceProperty>
15 </InstanceProperties>
16
17 </TargetMetadata>
18 ');

已创建 1 行。

SQL> COMMIT;

提交完成。

SQL> CREATE INDEX IND_T_DOCS ON T (DOCS) INDEXTYPE IS CTXSYS.CONTEXT
2 PARAMETERS ('SECTION GROUP CTXSYS.PATH_SECTION_GROUP');

索引已创建。

AUTO_SECTION_GROUP支持的自动节组属性,PATH_SECTION_GROUP同样支持:

SQL> SELECT ID FROM T WHERE CONTAINS(DOCS, 'COLLECTOR') > 0;

ID
----------
1

SQL> SELECT ID FROM T WHERE CONTAINS(DOCS, 'COLLECTOR WITHIN Display') > 0;

ID
----------
1

PATH_SECTION_GROUP还支持HASPATH和INPATH操作:

SQL> SELECT ID FROM T WHERE CONTAINS(DOCS, 'HASPATH(Display)') > 0;

未选定行

SQL> SELECT ID FROM T WHERE CONTAINS(DOCS, 'HASPATH(TargetMetadata/Display)') > 0;

ID
----------
1

SQL> SELECT ID FROM T
2 WHERE CONTAINS(DOCS, 'HASPATH(TargetMetadata/Display/Label="CSA COLLECTOR")') > 0;

ID
----------
1

HASPATH操作用来判断指定的路径在文档中是否存在。上面的三个查询中,第一个没有查询到内容是因为Display节组不是文档中最顶层的节组。第二个查询到内容是由于TargetMetadata是最顶层的节组,且TargetMetadata/Display路径存在。第三个查询展示了对于指定路径下的指定内容是否存在的查询。

SQL> SELECT ID FROM T WHERE CONTAINS(DOCS, 'COLLECTOR INPATH(TargetMetadata)') > 0;

ID
----------
1

SQL> SELECT ID FROM T WHERE CONTAINS(DOCS, 'COLLECTOR INPATH(Display)') > 0;

未选定行

SQL> SELECT ID FROM T WHERE CONTAINS(DOCS, 'COLLECTOR INPATH(//Display)') > 0;

ID
----------
1

INPATH操作和WITHIN操作比较类似,都是在指定的节组中进行查询。

由于Display不是顶层的节组,因此上面的第二个查询没有返回结果,而需要采用第三个查询。

SQL> SELECT ID FROM T
2 WHERE CONTAINS(DOCS, 'RECVFILEDIR INPATH(//InstanceProperty/@NAME)') > 0;

ID
----------
1

SQL> SELECT ID FROM T
2 WHERE CONTAINS(DOCS, 'RECEIVE INPATH(//Display[ShortName="Receive File Directory"])') > 0;

ID
----------
1

SQL> SELECT ID FROM T
2 WHERE CONTAINS(DOCS, 'RECEIVE INPATH(//InstanceProperties[.//ShortName="Receive File Directory"])') > 0;

ID
----------
1

最后列出了几个使用INPATH操作的复杂的查询,这里就不再一一解释了。通过上面的几个例子可以看出,使用INPATH操作比使用WITHIN更加的灵活。

 


原创粉丝点击