65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 Oracle Text 进行全文搜索

emptyStarIconemptyStarIconemptyStarIconemptyStarIconemptyStarIcon

0/5 (0投票)

2005 年 11 月 8 日

CPOL

4分钟阅读

viewsIcon

65625

downloadIcon

416

如何使用 Oracle Text 进行全文搜索。

Sample Image - ora_fulltext.gif

引言

您是否遇到过这样的问题:我需要找到硬盘上所有包含“Oracle”和“SQL Server”但不包含“MS Access”的文档。如果您有Oracle 10g和大约2个小时的时间,那么我可以向您展示一种使用Oracle Text轻松索引文档的方法。作为低技术方案的爱好者,您只需要一个文本编辑器和Oracle即可。我们将分三个步骤创建此解决方案

  • 使用SQL*Plus创建表、索引和存储过程
  • 使用VBScript导入文档
  • 创建用于搜索文档的用户界面 (GUI)

Oracle部分

首先,打开SQL*Plus来创建Oracle对象。首先,我们创建一个名为my_doc的新表,其主要字段为file_nameupload_datecontent

CREATE TABLE my_doc (
   id NUMBER,
   file_name VARCHAR2(255),
   upload_date VARCHAR2(10),
   filesize VARCHAR2(20),
   mime VARCHAR2(50),
   content BFILE,
 CONSTRAINT doc_pk PRIMARY KEY (id)
);

字段content定义为BFILE类型。这意味着文档的内容不会存储在Oracle中。这完全没问题,因为我们只需要索引。接下来我们将:定义一个目录,该目录将用作我们要索引的文档的根文件夹。授予用户ctxsys对此目录的读取权限。

CREATE OR REPLACE DIRECTORY documents AS 'C:\_work\datastore\';
GRANT READ ON DIRECTORY documents TO ctxsys;

接下来,我们创建一个CTXSYS.CONTEXT类型的索引

CREATE INDEX my_doc_idx ON my_doc(content) INDEXTYPE IS CTXSYS.CONTEXT 
    PARAMETERS ('SYNC ( ON COMMIT)');

最后,我们创建存储过程put_file

CREATE OR REPLACE PROCEDURE put_file
 (
  p_file_name  IN  my_doc.file_name%TYPE,
  p_upload_date IN my_doc.upload_date%TYPE,
  p_filesize IN my_doc.filesize%TYPE,
  p_mime IN my_doc.mime%TYPE
) AS
   index_name varchar2(20) := 'my_doc_idx';
 BEGIN
   INSERT INTO my_doc (id, file_name, upload_date,
   filesize, mime, content)
   VALUES (my_doc_seq.NEXTVAL, p_file_name, p_upload_date,
   p_filesize, p_mime,
   BFILENAME('DOKUMENTE',p_file_name));
   COMMIT;

就是这样——我们完成了Oracle对象的创建。现在我们可以使用SQL*Plus测试解决方案

exec put_file('test.doc', '10.10.2005', '100', 'doc');

执行上述语句时,请确保文件test.doc存在于已索引目录的根文件夹中。您还应使用以下语句检查表ctx_user_index_errors中的错误

SELECT err_index_name, err_timestamp,err_text FROM 
       ctx_user_index_errors ORDER BY err_timestamp;

如果此表中没有错误,请继续使用VBScript将更多文档插入表和索引中。要检查索引表的内容,您可以使用压缩的源文件中也包含的脚本index_stats.sql

导入数据

接下来,我们将创建一个简单的VBScript文件以导入特定文件夹中的所有文档。首先,我们打开数据库连接并访问根目录。我们使用过程put_file将目录中的每个文件插入到表my_doc中。最后,我们关闭数据库连接并清理所有已使用的对象。以下是VBScript文件的完整源代码

Dim strFolder: strFolder = "C:\_work\datastore\" ' index documents from this directory
' open database connection
Dim strCon: strCon = _
    "Driver={Microsoft ODBC for Oracle}; CONNECTSTRING=ORCL; uid=system;pwd=man;" 
Dim oCon: Set oCon = WScript.CreateObject("ADODB.Connection")
oCon.Open strCon
' insert record for each file
Dim oFs: Set oFs = WScript.CreateObject("Scripting.FileSystemObject")
Dim oFolder: Set oFolder = oFs.GetFolder(strFolder)
For Each oFile In oFolder.Files
 WScript.Echo oFile.Name
 Dim strCmd:
 strCmd = "put_file('" & _
   oFile.Name & "','" & _
   Date() & "','" & _ 
   oFile.Size & "','" & _ 
   oFs.GetExtensionName(oFile) & "')"
 oCon.Execute(strCmd)
Next
' cleanup
oCon.Close
Set oFolder = Nothing
Set oFs = Nothing
Set oCon = Nothing

这就是我们导入数据所需的一切。我尽可能简化了代码。您应该遍历目录结构以导入整个文档树。您可能还需要检查错误——读取表ctx_user_index_errors

用户界面

正如我在引言中承诺的那样,即使是用户界面,我们也只需要记事本。因此,我们使用HTA作为文档搜索的用户界面。为此,我们创建一个名为search.hta的文件。HTA使用Internet Explorer的GUI对象,但不需要Web服务器(如IIS)即可显示。首先,我们定义头部部分

<html>
<head>
<title>Indexed files</title>
<HTA:APPLICATION 
     ID="objTest" 
     APPLICATIONNAME="HTA Test"
     SCROLL="yes"
     SINGLEINSTANCE="yes"
>
</head>

请访问Microsoft网站http://www.microsoft.com/technet/scriptcenter/hubs/htas.mspx,了解更多关于HTA的信息。接下来,我们需要一个脚本部分来执行搜索并在HTA页面中显示结果。

<SCRIPT LANGUAGE="VBScript">
Sub StartQuery
 Dim strCon: strCon = "Driver={Microsoft ODBC for Oracle}; " & _ 
                      "CONNECTSTRING=ORCL; uid=system;pwd=man;"
 Dim oCon: Set oCon = CreateObject("ADODB.Connection")
 Dim oRs: Set oRs = CreateObject("ADODB.Recordset")
 oCon.Open strCon
 Dim strSql, strRes
 strSql = "SELECT SCORE(1), file_name, filesize FROM my_doc WHERE CONTAINS(content," & _
          Search.Value & ", 1) > 0 ORDER BY SCORE(1) DESC"
 strRes = "<table border=1 cellpadding=10 cellspacing=0><tr><th>found" & _ 
          "</th><th>title</th><th>size</th><th>action</th></tr>"
 Set oRs = oCon.Execute(strSql)
 While Not oRs.EOF
  strRes = strRes & "<tr><td>" & _
    oRs.Fields(0).Value & "</td><td>" & _
    oRs.Fields(1).Value & "</td><td>" & _
    oRs.Fields(2).Value & "</td><td><a href='datastore/" & _
    oRs.Fields(1).Value & "' target=_blank>Open in new windows</a>" & _
    "</td></tr>"
  oRs.MoveNext
 Wend
 oCon.Close
 strRes = strRes & "</table>"
 DataArea.InnerHtml = strRes
 Set oCon = Nothing
End Sub
</SCRIPT>

以下是上述代码中的一些要点

strSql = "SELECT SCORE(1), file_name, filesize FROM my_doc " & _
    WHERE CONTAINS(content," & Search.Value & ", 1) > 0 " & _
    ORDER BY SCORE(1) DESC"

这是一个对文件内容执行全文搜索的查询。例如:where条件CONTAINS(content, 'Perl', 1)仅选择包含字符串Perl的文档,并获取文档中匹配项的数量。变量Search.Value是稍后在HTA的主体部分定义的文本框的值。

DataArea.InnerHtml = strRes

使用HTML表格格式化结果后,我们将表格分配给'DataArea.InnerHtml'。对象DataArea也在HTA的主体部分定义。在这里,我们看到主体部分(我删除了一些格式化代码,如表格和图片),以简化内容

<body>
<input type="text" name="Search" size="60">
<input type="button" value="Start Query" 
      name="startQuery" onClick="StartQuery"><p> 
<p>
<span id = "DataArea"></span>
</body>

在主体部分,我们定义一个名为Search的文本区域。Search.Value的内容作为Select语句的输入。接下来,我们定义一个标题为“开始查询”的按钮,其事件处理程序调用脚本部分中定义的子例程StartQuery。最后,我们需要一个DataArea。我们将查询的格式化输出分配给'DataArea.InnerHtml'。

现在我们完成了——您可以通过双击资源管理器启动搜索界面。请参阅GUI中有效搜索的一些示例。有关文档搜索的更多信息,请查看:http://oraclesvca2.oracle.com/docs/cd/B13789_01/text.101/b10729/toc.htm

关注点

如您所见,使用Oracle Text为您的Office文档创建索引非常简单。但是在此解决方案中,我们只有文档内容的快照。如果您更改了文档会发生什么?该文档的索引将不再有效。因此,当文档发生更改时,我们应该注意更新索引。我已经有了一个解决这个问题的想法。

© . All rights reserved.