Oracle 数据库中的全文搜刮

打印 上一主题 下一主题

主题 889|帖子 889|积分 2667

0. 弁言

这篇文章会先容 Oracle Text 索引,旨在引导您了解创建文本索引、执行文本查询和维护文本索引的底子知识。
Oracle Text 为 Oracle 数据库提供全文索引功能,允许您通过指定内容中的单词、短语或其他文本模式来搜刮文本内容(比方 VARCHAR2 或 CLOB 数据)。
Oracle Text 是数据库的尺度组件,允许您在 Oracle 数据库中的文本数据中举行快速全文搜刮。比方,它可以让您在地点字段中查找拼写错误的单词,大概获取包含特定短语的 Microsoft Word 文档列表。
固然外貌上它类似于 LIKE 运算符的索引版本,但存在很多差异。
Oracle Text 对数据库中的文本内容创建基于单词(word-based)的索引。该内容的范围可以从 VARCHAR2 列中的几个单词到存储在 BLOB 列中的多章节 PDF 文档(甚至存储在文件系统外部、URL 或云存储上)。
这篇文章主要面向开发人员和 DBA,内容涵盖创建索引、根本搜刮功能和索引维护。
1. 整体流程

整体流程如下,
我们将创建一个名为“user_data”的简单表,此中包含客户信息。此中包括记录 ID 的数字列、客户名称的 VARCHAR2 列、订单金额的数字列以及贩卖代表所做的任何注释的 VARCHAR2 列。
我们将添补该表,然后在注释列上创建一个文本索引。
然后,我们将使用 Oracle Text CONTAINS 运算符完成各种类型的查询。我们还将在注释列上显示一些带有全文搜刮的混合查询,并在其他关系列上显示附加过滤器。
接下来,我们将了解如何同步和优化 Oracle Text 索引。
末了,我们将了解如何在对象存储上索引二进制文件,比方 Microsoft Word 或 PDF 文件。
2. 创建索引

2-1. 创建一个简单的表

我们将创建一个简单的表来保存模仿用户贩卖记录。它包含一个用于记录 ID 的数字列、一个用于客户名称的 varchar 列、另一个用于贩卖额的数字列以及另一个用于注释的 varchar 列。将以下内容复制到“工作表”区域,然后按“运行语句”按钮:
  1. create table user_data
  2. (id number,
  3. name varchar2(100),
  4. amount number(17,2),
  5. note varchar2(2000)
  6. )
复制代码
插入几行数据,
  1. insert into user_data
  2.     select 1, 'John Smith', 123.45, 'First order from John Smith.' from dual
  3.         union
  4.     select 2, 'Mary Poppins', 67.89, 'First ever order from Marie Poppins.' from dual
  5.         union
  6.     select 3, 'John Smith', 99.45, 'Second order from Johnny Smith.' from dual
  7. commit;
复制代码
查抄表中是否有数据,
  1. select * from user_data
复制代码
2-2. 创建文本索引

文本索引是域索引(domain index)的一个示例。域索引是特定类型数据(或“域”)的专门索引。为了告诉内核要创建什么类型的索引,我们使用特殊语法“INDEXTYPE IS …”。最常见的文本索引类型,也是我们在这里使用的,是 CONTEXT 索引类型。
复制并运行以下 SQL,这将在表的 TEXT 列上创建索引。
  1. create index myindex on user_data(note) indextype is ctxsys.context
复制代码
查抄数据库视图中的索引,
  1. select index_name, index_type, status from user_indexes
  2. where index_name = 'MYINDEX'
复制代码

如许就有了您的索引,index_type 为“DOMAIN”,状态为“VALID”。文本索引必须有用才能使用。在大型表上创建的索引大概会显示为 INPROGRS,这意味着索引创建正在举行中,但尚未准备好使用。
我们还可以在“文本数据字典”中查找。这是用户 CTXSYS 拥有的一组视图,专门用于 Oracle Text 索引。这些视图均以“CTX_”为前缀,所有用户都可以查看。运行以下命令:
  1. select idx_name, idx_table, idx_text_name from ctx_user_indexes
复制代码

这告诉我们索引 MYINDEX 是在表 USER_DATA 的“NOTE”列上创建的。
2-3. 查看创建的底子表

文本索引作为一组底子表来实现。它们通常接纳 DR                                   <                         i                         n                         d                         e                         x                         n                         a                         m                         e                         >                              <indexname>                  <indexname> 情势,此中后缀表示表的特定类型。通常不必要知道这些索引中有什么,但此中一个(“dollar I”表)特殊有趣。
留意:子表列表将随数据库版本和所选索引选项的不同而变化。您大概会看到与此处显示的列表不同的列表。
您应该看到列出了几个表。单击旁边的三角形,打开 DR                                   M                         Y                         I                         N                         D                         E                         X                              MYINDEX                  MYINDEXI 的表定义。
我们看到一个列列表。我们主要感爱好的是 TOKEN_TEXT。
我们之前讨论了 Oracle Text 如何使用“基于单词”的索引。更准确地说,它使用“基于令牌”的索引,由于令牌不肯定是单词(只管通常是)。 “$I”表包含所有索引标记的列表,我们可以使用以下查询查看它们:
  1. select token_text from dr$myindex$i
复制代码

留意到列表中的任何内容了吗?文本中并未出现所有单词 - 缺少“from”。这是由于它被指定为“停用词” - 在搜刮中不是很有用的常见词,但大概会占用索引中的大量空间。默认情况下,我们不会对它们创建索引 - 只管使用高级选项,我们可以告诉系统对所有单词创建索引,大概提供我们不想索引的单词的“自定义非索引字表”。默认的停用词列表将随语言的不同而变化,并且取决于数据库的默认语言设置(自治数据库始终为英语)。您可以按照此处的示例自定义停用词列表:创建停用词列表和添加停用词。
目前我们不必要了解任何有关底层索引表的信息。但查看已索引的单词很有用,并且在尝试找出特定查询为何云云运行时,偶然值得参考此列表(下一步将先容查询)。
3. 运行查询

我们将探讨用于查询 Oracle Text 索引的 CONTAINS 运算符。
在这个章节,您将:


  • 探索 CONTAINS 文本查询运算符
  • 查看各种根本文本搜刮
  • 了解 SCORE() 运算符如何资助您对查询效果举行排名
3-1. 运行文本查询

首先认识 USER_DATA 中包含的文本。
  1. select * from user_data
复制代码

3-2. CONTAINS 运算符

要搜刮 Oracle Text CONTEXT 索引,必须使用 CONTAINS 运算符。 CONTAINS 特定于该类型的索引。与“平常”索引不同,无论有没有索引,您都无法获得雷同的效果。假如不存在 CONTEXT 索引,CONTAINS 根本不起作用。
CONTAINS 是一个返回数字的函数。它几乎总是以 WHERE CONTAINS(…) > 0 的情势使用。假如返回值大于零,则该行有匹配项,假如为零则没有匹配项。
CONTAINS 必要两个或三个参数。第三个是可选的,我们稍后再讨论。两个必需的参数是:


  • 要搜刮的列的名称
  • 要搜刮的字符串值。该字符串可以是笔墨字符串,也可以是任何计算效果为字符串的字符串(VARCHAR2 或 CLOB)。
让我们尝试一个简单的例子。我们将查找单词“John”:
  1. select * from user_data
  2.      where contains ( note, 'john' ) > 0
复制代码

请留意,我们找到了包含单词“John”的一行。但是,我们没有找到包含“Johnny”的行。这阐明白 Oracle Text 搜刮与简单的 LIKE 搜刮(比方 WHERE TEXT LIKE ‘%John%’)之间的众多差异之一。 LIKE 执行子字符串搜刮,而 CONTAINS 则(默认情况下)查找整个单词。
您还可以尝试搜刮大写的 JOHN。你会得到雷同的效果。与 LIKE 搜刮不同,CONTAINS 搜刮(至少对于英文索引)不区分巨细写。
3-3. 混合查询

CONTAINS 是一个 SQL 运算符。当然,您可以将其与任何其他 WHERE 子句联合起来。比方,我们可以查找 AMOUNT 值小于 100 的单词“Smith”。让我们尝试一下:
  1. select * from user_data
  2.     where amount < 100    and   contains ( note, 'smith' ) > 0
复制代码

3-4. OR 查询

CONTAINS 的搜刮字符串参数有自己的语法,具有各种内部运算符,比方 AND、OR、NEAR 等。我们在这里仅展示一个示例,有关更多信息,您应该参阅文档。
之前,我们搜刮“John”但没有找到“Johnny”。让我们搜刮一下:
  1. select * from user_data
  2.      where contains ( note, 'john OR johnny' ) > 0
复制代码

果然,现在我们两者都找到了。
3-5. 通配符

运行先前搜刮的另一种方法是使用通配符 %。与尺度 SQL 一样,百分号 % 匹配任何字符串,下划线 _ 字符匹配任何单个字符。
因此 john% 将匹配“john”、“johnny”、“johnnie”、“johnston”等。 l_se 将匹配“lose”,但不匹配“loose”。
由于通配符仅适用于索引单词,因此它们永久不会匹配空格。因此 qui%step 将匹配“quickstep”,但不会匹配短语“quick step”。
我们来尝试一下:
  1. select * from user_data
  2.    where contains ( note, 'john%' ) > 0
复制代码

3-6. 短语搜刮

假如您想在同一文档中查找两个单词,您可以执行 AND 搜刮,类似于上面的 OR 搜刮。假如您想一起查找两个单词,只需将它们作为短语输入即可。无需添加引号或任何内容,两个单词一起自动构成短语搜刮,并且仅当它们一起出现在索引文本中时才会匹配。
  1. select * from user_data
  2.    where contains ( note, 'first order' ) > 0
复制代码

Note that only matches the first row where the actual phrase “first order” appears, and not the other row where the two words appear, but not as a phrase.
3-7. 模糊搜刮(Fuzzy searches)

假如您犯了错误或根本不记得确切的拼写,您可以举行模糊搜刮。它不仅会找到原始搜刮词,还会找到所有与其相似的搜刮词。
  1. select * from user_data
  2.    where contains ( note, 'fuzzy(popins)' ) > 0
复制代码

请留意,搜刮词“popins”存在拼写错误。但通过模糊搜刮,它现实上找到了包含正确单词“Poppins”的效果。
3-8. 附近的搜刮

您可以使用 NEAR 运算符查找相互接近的单词。它将查找相互指定距离内的单词。比方,以下查询未找到任何效果。由于“order”和“smith”之间有两个单词,但我们指定它们之间最多有 1 个单词。
  1. select * from user_data
  2.    where contains ( note, 'near((order, smith), 1)' ) > 0
复制代码

下一个查询找到效果,由于它正确指定了“order”和“smith”之间的距离 2。
  1. select * from user_data
  2.    where contains ( note, 'near((order, smith), 2)' ) > 0
复制代码

请留意,默认情况下,近运算符中的单词次序并不重要,除非 ORDER 参数显式设置为 TRUE。但在短语搜刮中,单词的次序确实很重要。
You can find a list of query operators here: Contains Query Operators.
4. 维护索引

到目前为止,我们已经了解了如何创建和查询 Oracle Text 索引。这是 Oracle Text 的底子知识,但我们必要讨论索引维护下的几个主题。
默认情况下,Oracle Text 索引不是事件性的。索引表发生更改后,必须先同步索引,然后才能通过搜刮找到新数据。
对 Oracle Text 索引举行多次更改后,由于索引碎片和垃圾(已删除)数据在索引中累积,其性能将达不到理想状态。为了让索引到达最佳状态,我们必须对其举行优化。
在本章节中,您将:


  • 看到索引没有自动更新
  • 了解如何手动或自动同步索引
  • 看到索引随着时间的推移变得碎片化
  • 了解如何优化索引
4-1. 同步

让我们向 USER_DATA 中插入一个新行。复制以下内容并单击“运行语句”按钮:
  1. insert into user_data values (4, 'Mike Smith', 98.76, 'Third one from Mike Smith.');
  2. commit;
复制代码
现在尝试查询刚刚插入的数据:
  1. select * from user_data
  2.     where contains ( note, 'mike' ) > 0
复制代码
当你运行它时,你将不会得到任何效果。请记住 CONTAINS 仅适用于 CONTEXT 索引。假如该索引不是最新的,那么效果也不会是最新的。为了获得正确的效果,我们必须同步索引。执行此操纵的根本方法是调用 PL/SQL 过程 CTX_DDL.SYNC_INDEX(您的用户必要具有 CTXAPP 脚色才能访问该过程,大概已被显式授予 EXECUTE ON CTXSYS.CTX_DDL)。索引名称作为参数通报给过程。
运行这个命令同步索引,
  1. execute ctx_ddl.sync_index ('myindex')
复制代码
现在再次尝试之前的“mike”查询,它将起作用。
4-2. 提交时自动同步

手动运行 SYNC_INDEX 非常高效,并且可以让您完全控制。但是,您可以让索引自动同步,方法是指定应在提交时同步,大概指定定期的时间段(比方每分钟)来执行同步。
首先删除当前索引:
  1. drop index myindex
复制代码
每当必要非默认索引行为时,我们都会对索引使用 PARAMETERS 子句。这里我们将指定 SYNC(ON COMMIT) 以使其在 COMMIT 时自动同步:
  1. create index myindex on user_data(note) indextype is ctxsys.context
  2.     parameters ('sync (on commit)')
复制代码
现在我们将向表中添加一个新行并搜刮它:
  1. insert into user_data values (5, 'Peter Williams', 110.68, 'Canceled order from Peter Williams.' );
  2. commit;
复制代码
我们将找到新行,而无需调用 CTX_DDL.SYNC_INDEX。
  1. select * from user_data
  2.      where contains ( note, 'williams' ) > 0
复制代码
4-3. 按时间隔断自动同步

SYNC(ON COMMIT) 很方便,但在高事件率情况下并不理想。它大概会导致事件在等待上一个 SYNC 完成时被耽误。相反,您可以选择在特定时间段执行 SYNC。
该时间段越长(通常选择五分钟),您的索引必要优化的次数就越少。但是,假如您必要近乎实时的同步,则可以选择低至一秒的时间段。
时间隔断SYNC使用数据库调理步伐,因此在19c及之前您必须具有CREATE JOB权限才能使用它。
删除现有索引:
  1. drop index myindex
复制代码
现在再次创建索引,但这次指定应每分钟同步一次。时间段的语法来自 DBMS_SCHEDULER。
  1. create index myindex on user_data(note) indextype is ctxsys.context
  2.     parameters ('sync (every "freq=minutely; interval=1")')
复制代码
现在插入一个新行
  1. insert into user_data values (6, 'Paul Williams', 77.36, 'Returned order from Paul Williams.' );
  2. commit;
复制代码
搜刮新行。最初,您大概会发现它找不到新行,但继续重复查询,它会在一分钟内起作用。
  1. select * from user_data
  2.      where contains (note, 'paul') > 0;
复制代码
4-4. 优化

查抄“$I”表,现在我们已经完成了索引的更新,让我们再看一下 $I 表中的索引词列表。运行以下命令:
  1. select token_text from dr$myindex$i
复制代码

您应该看到现在有两个单词“order”和“williams”的条目。我们不会担心到底为什么(只管请留意它们是在上次更新中使用的),但我们只是说这是索引碎片的一个示例。
优化索引,我们可以使用 ctx_ddl 包中的另一个 PL/SQL 命令来优化索引:ctx_ddl.optimize_index。这必要两个强制参数:索引名称和要执行的优化类型。常见值为“FULL”或“REBUILD”。我们将选择“FULL”:
  1. execute ctx_ddl.optimize_index('myindex', 'FULL')
复制代码
现在再次尝试从 $I 表中举行先前的选择。现在只有一个“order”条目和一个“williams”条目 - 这些单词的索引信息已被压缩为每个单词的一行。

您现在应该在创建 Oracle Text 索引、针对这些索引运行根本查询以及维护这些索引方面具备良好的底子。
5. 对象存储上的索引文件

在之前的实验中,我们向您展示了如何对简单的 VARCHAR2 文本举行索引。但 Oracle Text 的能力远不止于此。比方,它可以自动识别和处理约莫 150 种不同的二进制文件格式。有 PDF 文档吗?没问题。想要索引 Powerpoint 演示文稿中的所有文本吗?当然可以,为什么不呢?
Oracle Text 可以处理文件系统或 URL 上保存的文件,但对于本例,我们将把文件直接加载到数据库的 BLOB(二进制长对象)列中。
完成之前的所有实验后,此实验是可选的。您可以索引自己的文件,或使用我们提供的简单的 Microsoft Word 文件。
在本章节中,您将:


  • 将文件复制到对象存储
  • 创建“预授权哀求”URL 来访问这些文件
  • 使用 DBMS_CLOUD.GET_OBJECT 将文件加载到数据库中
  • 创建一个首选项,告诉 Text 使用 AUTO_FILTER
  • 索引文件并使用内容词举行搜刮
5-1. 将文件加载到对象存储

转到 Oracle Cloud 中的主菜单(请留意,这与数据库操纵的菜单不同 - 它大概在不同的选项卡中打开)。
打开“汉堡包”菜单,然后选择“存储”,然后选择“对象存储和归档存储”下的存储桶。
在“存储桶”页面中,从“搜刮分区”框中选择您的根分区。
然后点击“创建存储桶”,您可以提供名称或仅保存默认名称。单击创建。
现在单击新创建的存储桶。
滚动到页面底部找到对象并单击上传。
在“上传对象”面板中,您可以使用文件选择器从计算机中选择某些 Office 或 PDF 文件,或将它们拖放到页面上。
假如您没有任何符合的文件,您可以从这里下载一个简单的 Microsoft Word 文档。
关于 PDF 文件的阐明:Oracle Text 无法处理纯图像的 PDF 文件(纵然它们是文本图像 - 我们没有 OCR 功能)。 PDF 文件必须嵌入文本。偶然,PDF 文件会受到文本访问掩护,或使用无法读取的特殊“位图”字体。不过,绝大多数 PDF 文件都可以使用。
选择文件后,单击“上传”按钮即可完成。然后单击“关闭”,您应该会看到存储桶中列出了您的文件。
为文件创建预验证哀求 (PAR)。
对于存储桶中的每个文件,我们必要创建一个“预验证哀求”。这是一个特殊的 URL,此中包含文件的嵌入式访问密钥。这意味着任何有权访问该 URL 的人都可以访问该文件,但现实上不大概猜测该 URL。
单击文件右侧的“三点”菜单,然后选择“创建预验证哀求”。
在弹出的面板上,选择“对象”,然后单击“创建预验证哀求”按钮。
您将看到一个“预验证哀求详细信息”面板,单击“复制”按钮复制 URL,然后将其保存到文本文件以供以后使用。对每个要索引的文件重复此操纵。
留意:不要担心可骇的“不会再显示”。您可以随时创建另一个 PAR。
5-2. 将文件加载到数据库中

在浏览器中打开“数据库操纵”选项卡(大概假如必要,可以使用之前的阐明重新打开它)并转到 SQL。
创建一个表来保存文件数据。运行以下语句:
  1. create table documents (name varchar2(50), content blob)
复制代码
将文件从对象存储加载到表中。
对您存储的每个文件运行一次,更换为 PAR URL(您在上一步中保存的)和短名称或形貌。不要忘记为每个文件指定不同的名称/形貌。
  1. declare
  2.    body blob;
  3. begin
  4.    body := dbms_cloud.get_object(null, 'https://objectstorage.uk...HelloWorld.docx');
  5.    insert into documents values ('Hello World as an MS Word file', body);
  6. end;
复制代码
通过获取名称和 LOB 列的巨细来查抄文件是否已正确加载
  1. select name, dbms_lob.getlength(content) from documents
复制代码
5-3. 索引文档

创建过滤器首选项。
Oracle Text 很聪明地发现,假如它对 BLOB 列创建索引,那么它显然是在处理二进制文件,必要通过 AUTO_FILTER 才能被识别并转换为文本。所以现实上我们可以像从前一样创建一个简单的文本索引。但为了阐明如何自定义索引选项,我们将向您展示如何创建一个首选项,明白告诉文本使用 AUTO_FILTER,覆盖其索引的数据类型的任何默认值。我们还将根据我们的偏好设置一个 TIMEOUT 属性,告诉它过滤任何特定文件的时间不要超过 10 秒。
我们必要创建一个首选项,然后设置该首选项的属性。这些都是使用名为 ctx_ddl 的包完成的,任何具有 CTXAPP 脚色的用户都可以执行该包。由于这里有两个语句,因此使用“运行脚本”按钮运行它们是最简单的。大概,突出显示这两个语句并按“运行”。
  1. exec ctx_ddl.create_preference ('my_filter_pref', 'AUTO_FILTER')
  2. exec ctx_ddl.set_attribute ('my_filter_pref', 'TIMEOUT', 10)
复制代码
(假如您必要再次运行该步伐,您可以调用 ctx_ddl.drop_preference,仅将首选项名称作为参数)
使用我们的过滤器首选项创建索引。
对于任何具有非尺度选项的索引,我们使用 PARAMETERS 子句(我们之前在 SYNC 选项中看到过它)。该子句接纳单个字符串,该字符串主要是首选项类型和首选项名称的列表。在这里,我们的首选项类型是“filter”,首选项名称是“my_filter_pref”。假如我们想添加更多文件,我们还将包括同步(提交时)。
  1. create index documents_index on documents(content)
  2.   indextype is ctxsys.context
  3.   parameters ('filter my_filter_pref sync(on commit)')
复制代码
假如该语句出现任何问题 - 就像您拼写错误您的偏好一样,它大概会创建失败的索引。在创建新索引之前,您必要删除该索引。
5-4. 搜刮文件

我们的 CONTAINS 将针对索引的 CONTENT 列运行,但由于它是二进制的,因此没有须要选择它,因此我们只需选择 NAME 列。假如您不为 HelloWorld 文档体例索引,则可以在此处更换为您自己的搜刮字符串。
  1. select name from documents where contains (content, 'world') > 0
复制代码
可选:获取片断(上下文中突出显示的搜刮词)
我们无法读取表中的二进制文档,但我们可以让 Text 用它来做一些事变。 CTX_DOC 包有各种处理索引文档的过程。让我们看一下 CTX_DOC.SNIPPET,它获取搜刮词周围的文档块。它通常从 PL/SQL 调用,但假如我们传入索引名称和我们正在查看的行的 ROWID 值,我们也可以从 SQL SELECT 查询调用它。我们还必须告诉它所使用的搜刮词。所以我们得到:
  1. select name, ctx_doc.snippet('DOCUMENTS_INDEX', rowid, 'world') from documents where contains (content, 'world') > 0
复制代码
假如您正在搜刮其他文档,请不要忘记将“world”更改两次。
CTX_DOC包含很多用于处理单个文档的函数。值得一看文档。
假如您已完成此可选模块,您就会知道 Oracle Text 可以处理的不仅仅是数据库中的短文本。为什么不尝试更多的文件呢?也许将“文档”文件夹中的所有文件加载到数据库中,最终,您将可以或许找到您多年前编写的难以捉摸的 Powerpoint,但不记得它的文件名。
6. (可选)情感分析

情绪分析可以回答“产品评论是正面还是负面?”等问题。或“客户满意还是不满意?”比方,从包含特定产品的多个评论的文档会合,您可以确定表明该产品是好还是坏的总体情绪。
Oracle Text 使用户可以或许使用经过训练以识别情感元数据的情感分类器对主题或文档执行情感分析。
Oracle Text 可以使用根本的内置“词袋”分类器(针对英文文本)执行情感分析。为了获得更好的效果或使用其他语言,您可以使用一组培训文档来训练您自己的分类器。
本章节将使用Oracle数据库创建一个分类器,并用它来分析一组有关相机评论的文档的情绪。
在本章节中,您将:


  • 使用内置的默认分类器分析文档的情绪
  • 使用单独的训练文档集训练自定义分类器
  • 使用经过训练的分类器来分析文档
  • 比较两种分析方法的准确性
6-1. 使用默认分类器

加载评论数据举行分析,这是您要分析的现实数据。在本例中,我们将创建一个“camera_review”表并将评论文本加载到该表中。
  1. create table camera_reviews(review_id number primary key, review_text varchar2(2000))
复制代码
插入评论数据。您必要在运行之前选择所有行,大概使用“运行 SQL 脚本”按钮,
  1. insert into camera_reviews values (1, 'this camera is OK');
  2. insert into camera_reviews values (2, 'the camera is absolutely fantastic');
  3. insert into camera_reviews values (3, 'the camera is terrible');
  4. insert into camera_reviews values (4, 'another fantastic camera from Nikon');
  5. insert into camera_reviews values (5, 'What a terrible camera from Canon');
  6. insert into camera_reviews values (6, 'camera is not too bad, but ok for the price');
  7. insert into camera_reviews values (7, 'lens is not too bad, love the looks of this camera');
  8. insert into camera_reviews values (8, 'the Sony camera has a lot of new features, although a bit pricey');
复制代码
查抄所有行是否已加载。您应该看到 8 行。
  1. exec ctx_ddl.create_preference('review_lexer', 'AUTO_LEXER')
复制代码
使用我们刚刚创建的首选项和 NOPOPULATE 关键字创建评论数据的索引,
  1. create index camera_revidx on camera_reviews(review_text)
  2. indextype is ctxsys.context
  3. parameters ('lexer review_lexer NOPOPULATE');
复制代码
6-2. 运行情绪分析

情绪分析使用 PL/SQL 过程 CTX_DOC.SENTIMENT_AGGREGATE 逐行运行。返回一个数值,表示文档的情绪,范围在 -100 到 100 之间,此中 -100 最大为负面,0 为中性,100 最大为正面。该函数接纳索引的名称和 TEXTKEY,TEXTKEY 可以是行的唯一键值,大概假如表没有唯一键,则为 ROWID 值(我们可以使用 CTX_DOC.SET_KEY_TYPE 在使用键和 rowids 之间举行交换。
因此,为了获取每个评论文本及其计算出的情绪,我们可以运行以下命令:
  1. select ctx_doc.sentiment_aggregate(
  2.     index_name => 'camera_revidx',
  3.     textkey    => review_id
  4.   ) sentiment, review_text
  5. from camera_reviews;
复制代码
6-3. 使用经过训练的分类器

训练分类器涉及提供一组已知为正面、中性或负面的训练文档。此类文档大概已经过人工审核,大概您大概会使用用户提供的其他元数据(比方星级评定)。
训练使用称为支持向量机(SVM)的呆板学习算法。
您提供的训练文档越多,分类器就越好。由于我们在这里只提供很少的示例文档,因此分类器将非常粗糙。
加载训练数据,我们将加载评论培训表。在下一步中,我们将为每条评论贴上相关情绪的标签。
首先,创建一个名为“training_camera”的表来保存训练数据,
  1. create table training_camera(train_id number primary key, train_text varchar2(2000))
复制代码
将训练数据插入训练表,
  1. insert into training_camera values( 1,'this camera is OK');
  2. insert into training_camera values( 2,'the camera is absolutely fantastic');
  3. insert into training_camera values( 3,'the camera is terrible');
  4. insert into training_camera values( 4,'i love the lens, but overall ok camera');
  5. insert into training_camera values( 5,'the camera has mediocre lens, but a lot of nice features');
  6. commit;
复制代码
用情感标记训练数据,我们使用一个单独的表来保存与“training_camera”表中每一行相关的情绪:
  1. create table training_category(doc_id number, category number, category_desc varchar2(100))
复制代码
对于训练数据表中的每一行,我们必须插入一行来指示该行的类别。类别是代表中性、正面或负面的整数值,如下表所列。 “categoy_desc”列作为人类可读的注释包含在此处,在分类过程中既不是必需的,也不是使用的。
整数意义0中立1积极2负 鉴于此,我们可以如下创建类别行(您大概希望返回训练表以查抄每行涉及的文本)
insert into training_category values( 1, 0, ‘neutral’);
insert into training_category values( 2, 1, ‘positive’);
insert into training_category values( 3, 2, ‘negative’);
insert into training_category values( 4, 0, ‘neutral’);
insert into training_category values( 5, 0, ‘neutral’);
6-4. 创建 SVM 情感分类器

  1. exec ctx_ddl.create_preference('classifier_camera','SENTIMENT_CLASSIFIER')
复制代码
您可以选择设置分类器“classifier_camera”的属性。
  1. exec ctx_ddl.set_attribute('classifier_camera','MAX_FEATURES','1000');
  2. exec ctx_ddl.set_attribute('classifier_camera','NUM_ITERATIONS','600');
复制代码
6-5. 索引训练集

在训练表上创建索引。该索引仅用于其关联的元数据,因此可以使用“nopopulate”选项创建,并且速度非常快。对于经过训练的分类器,您确实必要使用 AUTO_LEXER,我们将允许它使用默认的英语词法分析器 (BASIC_LEXER)。
  1. create index training_idx on training_camera(train_text)
  2. indextype is ctxsys.context parameters ('nopopulate');
复制代码
6-6. 训练分类器

过程 SA_TRAIN_MODEL(SA 用于情感分析)获取有关训练和类别表(及其各个列)的信息,以及我们刚刚创建的索引和分类器首选项的名称。然后,这将生成一个模子,其名称在第一个参数中给出 - 在本例中为“my_clsfier”
  1. begin
  2.   ctx_cls.sa_train_model (
  3.     clsfier_name => 'my_clsfier',
  4.     index_name   => 'training_idx',
  5.     docid        => 'train_id',
  6.     cattab       => 'training_category',
  7.     catdocid     => 'doc_id',
  8.     catid        => 'category',
  9.     pref_name    => 'classifier_camera'
  10.     );
  11. end;
复制代码
6-7. 使用经过训练的分类器运行情感分析

运行情感分析的过程与上次非常相似,只是这次我们必要提供分类器名称,而不是允许其默认。
请记住,我们在camera_reviews 表上已经有一个“nopopulate”文本索引 - 假如我们在上一步中没有创建它,我们必要在使用新分类器之前在此处创建它。
  1. select ctx_doc.sentiment_aggregate(
  2.     index_name   => 'camera_revidx',
  3.     textkey      => review_id,
  4.     clsfier_name => 'my_clsfier'
  5.   ) sentiment, review_text
  6. from camera_reviews;
复制代码
我们还可以在同一个查询中运行经过训练和未经训练的分类器,以比较两者的效率。当然,这是一个经心选择训练词的人为示例,但在现实世界中,假设训练集巨细公道,您应该会看到经过训练的分类用具有明显更好的性能。
  1. select review_text,
  2.   ctx_doc.sentiment_aggregate('camera_revidx', review_id) as default_sentiment,
  3.   ctx_doc.sentiment_aggregate('camera_revidx', review_id, clsfier_name => 'my_clsfier') as trained_sentiment
  4. from camera_reviews order by trained_sentiment;
复制代码
You can find more details of sentiment analysis here: [Sentiment Analysis](You can find more details of sentiment analysis here: Sentiment Analysis.
).
refer: Full-Text Search in Oracle Database ShareStart
完结!

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

钜形不锈钢水箱

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表