spotweb/fts_parser

TSearch2和PostgreSQL全文搜索解析器

1.0.0 2022-02-17 14:55 UTC

This package is auto-updated.

Last update: 2024-09-17 21:18:45 UTC


README

最新动态

2008年3月31日: 版本2.0发布
在完全重写后发布2.0版本,以修复1.0版本中发现的一些错误,并添加新功能。我只为PHP5编写了版本2,所以如果你还在使用PHP4(你真的应该考虑升级)的话,你将不得不自行进行适当的修改。实际上,PHP4和非PHP4之间的区别主要是使用PHP5的类常量而不是全局定义。

2006年7月14日: 首次发布
TSearch2和PostgreSQL全文搜索解析器正式发布,但并未引起太多关注。

描述

这是一个用PHP编写的全文搜索解析器,用于与TSearch2扩展一起使用PostgreSQL。TSearch2为任何Postgres数据库添加了一个功能齐全、集成且快速的全文搜索,但其搜索语法使用&和;表示AND,|表示OR,!表示NOT,这些更适合程序员而不是一般会使用搜索的用户。大多数人只是想输入单词,在这种情况下,通常假设单词之间有一个"AND"操作。最后,当搜索完成后,用户通常喜欢看到搜索词在结果集中高亮显示。我编写了这个解析器来解决上述所有问题,并且它目前正在实际应用中部署。我还想涉足编写语言和解析器,所以这是一个很好的方式来介绍自己,而不会过于复杂。

这需要花费多少费用?

我正在以BSD开源许可证发布PHP源代码,所以基本上是免费的。然而,如果你在商业项目中使用此代码,捐赠将会非常受欢迎。

要求

系统要求如下

  1. 安装了带有TSearch2扩展的PostgreSQL数据库。
  2. PHP 5.x

特性

以下是解析器的核心特性

  • 简单易用。
  • 完全使用PHP编写,无依赖项。
  • 允许用户以自然方式输入搜索字符串,并在关键字之间应用默认的"AND"或"OR"。
  • 提供适合用户消费的错误信息。
  • 支持使用括号进行无限深度的表达式嵌套。
  • 支持使用双引号或单引号进行精确短语搜索。
  • 可以生成用于作为正常SQL查询或创建预编译语句的结果。
  • 返回用于突出显示结果集的单个关键词数组。

安装和配置

安装

解压缩.tgz文件,你会得到三个文件

  • parse_model.php - 主要解析器代码。我使用MVC(模型、视图、控制)模式设计和编写我的代码,解析器是一个模型。在这种情况下,它只定义了一个类,所以它应该可以作为任何项目的即插即用模块。
  • parse_test.php - 一个简单的测试程序,可以从浏览器中运行。
  • parse_test_cmd.php - 与上面的测试程序相同,但可以从命令行运行。

将parse_model.php文件放入您的项目目录中,并在需要解析器的地方包含它。这里有一个非常简单的示例

require_once 'parse_model.php';

// Get input into $text via form post or command line...
$text = '("black and white" or "cut \'n dry") and not (gray | grey)';

$o_parse = new parse_model();
$o_parse->debug = true;
$o_parse->use_prepared_sql = true;

$o_db = new PDO('pgsql:host=localhost;dbname=mydb', 'user', 'pass');

if ( $text != '' )
{
    if ( $o_parse->parse($text, 'fulltext') == false )
        echo "Message to user: [$o_parse->error_msg]\n\n";
    else
    {
        $query = "SELECT * FROM some_table WHERE ";

        // The tsearch clause does NOT come back escaped.
        if ( $o_parse->tsearch != '' )
            $query .= "fulltext @@ to_tsquery(" . $o_db->quote($o_parse->tsearch) . ") ";

        // When $o_parse->use_prepared_sql is true, the values for the ILIKE are NOT
        // escaped, otherwise the clause that comes back will have single quotes
        // escaped with the character passed to the parse() function (which uses a
        // single quote as the default).  Because of how the ILIKE statement has to
        // be built, the escaping must be performed at parse time.
        if ( $o_parse->ilike != '' )
            $query .= ($o_parse->tsearch != '' ? "AND " : '') . "($o_parse->ilike)";

        echo "\nSample Query: $query\n\n";

        $o_q = $o_db->prepare($query);

        // Bind the ILIKE clause variables because $o_parse->use_prepared_sql was
        // set to true.  PDO will ensure the values are escaped properly (one of
        // the many reasons for using PDO).
        foreach ( $o_parse->db_ilike_data as $varname => $value )
            $o_q->bindValue($varname, $value);

        $o_q->execute();
    }
}

配置

确保 stop_words() 函数中的停用词数组与为您的 TSearch2 安装定义的同一列表匹配,通常位于:/usr/local/pgsql/share/contrib/english.stop

使用解析器

包含 parse_model.php 文件并创建一个解析对象

require_once 'parse_model.php';
$o_parse = new parse_model();

parse_model 类 API

输入变量成员

  • $debug 是一个布尔值,用于启用或禁用调试信息。默认为 false。在生产环境中,您当然希望将其设置为 false。在调试模式下,解析器将使用 echo 语句输出调试信息,这肯定会将输出输出到浏览器或命令行。

  • $upper_op_only 是一个布尔值,用于确定基于单词的操作符 "AND"、"OR" 和 "NOT" 是否必须由用户以大写形式输入才被视为操作符。默认为 false。

  • $use_prepared_sql 是一个布尔值,用于确定生成的 ILIKE 语句是处于预定义语句格式(推荐)还是常规 SQL 格式。当为 false 且输出为常规 SQL 时,任何单引号都将使用 PostgreSQL 特定的双引号方式转义。默认为 true。

  • set_default_op($op) 是一个布尔值,用于确定生成的 ILIKE 语句是处于预定义语句格式(推荐)还是常规 SQL 格式。当为 false(输出为常规 SQL)时,任何单引号都将使用 PostgreSQL 特定的双引号方式转义。默认为 true。

函数成员

  • set_default_op($op) 用于设置默认操作符,用于注入到搜索词和没有操作符的引号短语之间。可以是 "and"、"or" 或 "none"。默认为 "and"。

  • parse($text, $db_field) 将输入 $text 解析为 TSearch2 和 ILIKE 部分,如果发生错误则返回 false,否则返回 true。如果返回值为 false,则 $error_msg 变量将包含一个可读的错误消息,而 $keywords、$tsearch、$ilike 和 $db_ilike_data 的内容未定义,不应使用。$db_field 参数应设置为要在结果中的 TSsearch2 和 ILIKE 部分使用的数据库表字段名称。

输出变量成员

  • $keywords 是一个数组,其中填充了所有找到的关键词。

  • $tsearch 是一个字符串,包含 SQL WHERE 子句的 TSearch2 部分。

  • $ilike 是一个字符串,包含 SQL WHERE 子句的 ILIKE 部分,可以是预定义语句格式或常规 SQL。

  • $db_ilike_data 是一个数组,其中包含 ILIKE 预定义语句引用作为键,搜索字符串作为值。

  • $error_msg 是一个字符串,如果 parse() 返回 false,则包含一个可读的错误消息。

  • $error_tok 是一个字符串,包含发生错误的位置。

  • $error_pos 是一个整数,表示原始字符串中发生错误的字符偏移量。

注意

TSearch2 表面上看起来很复杂,但实际上安装、设置甚至添加到现有数据库都非常简单!如果您尚未开始使用 TSearch2,我建议阅读介绍页面以开始使用 TSearch2。

编写完整的解析器而不是尝试一大堆复杂的正则表达式的主要原因之一是处理短语搜索(双引号或单引号中的文本)。TSearch2 是一个单词索引器,因此无法执行真正的短语搜索。例如,如果搜索 'computer & programmer',TSearch2 将返回包含这两个单词的所有匹配项,但它们不一定紧挨在一起,这可能无关紧要。然而,如果搜索 '"computer programmer"',表明您想要该短语,即这两个单词必须出现在文本中,并且它们必须是连续的,TSearch2 无法保证这种匹配。

在TSearch2中包含短语搜索的方法是在SQL语句的WHERE子句中包含LIKE或ILIKE(不区分大小写的LIKE)。然而,当尝试从用户提供的搜索字符串中提取任何短语时,由于支持完全嵌套括号,问题会变得稍微复杂一些。ILIKE子句还必须在单个搜索中可能多个短语之间保留逻辑(AND、OR和NOT)。例如,如果有人搜索了:“计算机('c++' 或 'visual basic')”那么ILIKE将会是:“AND (text ILIKE '%c++%' OR text ILIKE '%visual basic%')”。将ILIKE表达式附加到WHERE子句上是使用AND,但这两个短语是一个OR条件,必须保留。

鉴于复杂性,我一开始就决定用真正的解析器来做这件事,而不是试图使用正则表达式。然而,也可能是因为我的正则表达式知识不足以完成任务,因为我知道正则表达式支持递归反向引用,但我从未深入研究过正则表达式。无论如何,我还是想写一个解析器... :-)

我还有一些关于在结果集中突出显示关键字和短语的意见,但已经很晚了,我需要睡觉。这些意见将会后续提供,但简而言之,这与TSearch2 "stemms"它索引和搜索的词有关。