搜索引擎关键词解析器

8
这是我想做的事情:
我需要创建一个搜索引擎解析器,使用以下运算符:
- 苹果 AND 橘子(AND 运算符) - 苹果 OR 橘子(OR 运算符) - 苹果 AND NOT 橘子(AND NOT 运算符) - "苹果"(引号运算符) - 苹果 AND (橘子 OR 梨)(括号运算符) - Appl*(星号运算符)
通过 preg_replace,我设法将字符串转换为数组,然后解析该数组以获取 MySQL 查询语句。 但我不喜欢这种方式,而且非常不稳定!
我在网上搜索了一些脚本来实现这个功能,但没有找到任何帮助!
请问有人可以帮我实现这个吗?
谢谢。

通常情况下,您首先对输入进行标记化,然后在标记化的数据上运行解析器。我的 print_r 转换器 做了类似的事情,但它有不同的语法。 - hakre
5个回答

3

好的,这将是一个较长的回答。

我认为您需要一个解析器生成器。这是一款能够根据给定语法生成代码以解析文本的软件。这些解析器通常由两个主要组成部分组成:词法分析器和语法分析器。词法分析器识别TOKENS(单词),语法分析器检查标记顺序是否符合您的语法。

在词法分析器中,您应该声明以下标记

TOKENS ::= (AND, OR, NOT, WORD, WORDSTAR, LPAREN, RPAREN, QUOTE)
WORD ::= '/w+/'
WORDSTAR ::= '/w+\*/'

语法应该像这样定义:

QUERY ::= word
QUERY ::= wordstar
QUERY ::= lparen QUERY rparen
QUERY ::= QUERY and QUERY
QUERY ::= QUERY or QUERY
QUERY ::= QUERY and not QUERY
QUERY ::= quote MQUERY quote
MQUERY ::= word MQUERY
MQUERY ::= word

这个语法定义了一个具有所需功能的语言。根据您使用的软件,您可以定义函数来处理每个规则。这样,您就可以将文本查询转换为SQL where子句。
我不是很擅长PHP,但我在网上搜索了解析器生成器,找到了PHP_ParserGenerator
请记住,只要您的数据库增长,这些查询可能会成为结构化存储系统的问题。
您可能需要尝试全文搜索引擎,以便执行此和许多其他与文本搜索相关的功能。这就是IndexTank的工作方式。
首先,您需要将所有数据库记录(或文档)添加到IndexTank中(或在搜索方言中进行索引)。
$api = new ApiClient(...);
$index = $api->get_index('my_index');
foreach ($dbRows as $row) {
  $index->add_document($row->id, array('text' => $row->text));
}

在此之后,您可以使用任何想要的运算符在索引中进行搜索

$index = $api->get_index('my_index');
$search_result = $index->search('Apples AND Oranges');
$search_result = $index->search('Apples OR Oranges');
$search_result = $index->search('Apples AND NOT Oranges');
$search_result = $index->search('"apples oranges"');
$search_result = $index->search('Apples AND ( Oranges OR Pears )');
$search_result = $index->search('Appl*');

我希望我回答了你的问题。


1

1
MySQL内置的文本搜索功能很好,适用于基本的自然语言文本搜索。但是,如果您想查询其他类型的文本、允许高级选项或搜索少于四个字母的单词,则通常需要更有创意的方法。 - Steven
IN BOOLEAN MODE 几乎完全满足了OP所要求的,并且将最小单词长度设置为较低也很容易。这将是一个非常简单的操作符替换。+1。 - Wrikken

0

0
你可以自己动手编写以下代码(重要提示: $search 字符串必须先进行过滤,否则会被黑客攻击)...
if (substr($search[0]=='*' and substr($search,-1)=='*') {
    // *ppl*
    $query = "SELECT * FROM `table` WHERE `field` LIKE (%'". str_replace('*','',$search) ."%')";
} elseif (substr($search,-1)=='*') {
    // Appl*
    $query = "SELECT * FROM `table` WHERE `field` LIKE ('". str_replace('*','',$search) ."%')";
} elseif ($search[0]=='*') {
    // *Appl
    $query = "SELECT * FROM `table` WHERE `field` LIKE ('%". str_replace('*','',$search) ."')";
} elseif (substr_count($search,'"')==2) {
    // " Apples " ... just remove the "
    $query = 'SELECT * FROM `table` WHERE `field` = "'. str_replace('"','',$search) .'"';
} elseif (strpos($search,')') or strpos($search,'(')) {
    // uh ... something more complex here
    $query = '#idunno';
} else {
    // the rest
    $query = 'SELECT * FROM `table` WHERE `field` = "'. $search .'"';
    $search  = array(
        ' AND ',
        ' OR ',
        ' AND NOT '
        );
    $replace = array(
        '" AND `field` = "',
        '" OR `field` = "',
        '" AND `field != "'
        );
    str_replace($search,$replace,$query);
}

-1

试试这个:http://www.isearchthenet.com/isearch/index.php

从自述文件中:

  • 搜索通常使用“可能包含”单词进行。匹配需要页面上输入的任何一个单词。
  • 您可以通过在单词前加上加号(+)来搜索包含特定单词的页面。只会显示包含该单词的页面。
  • 您可以通过在单词前加上减号(-)来忽略包含特定单词的所有页面。任何包含该单词的页面都不会显示在搜索结果中。
  • 您可以通过用双引号(“)括起来来搜索特定短语。只会显示包含该确切短语的页面。

它易于安装和使用。还可以看看http://sphinxsearch.com/ - 最强大的引擎,但不适合新手。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接