2011-07-29 226 views
8

这是我想做的事:搜索引擎关键词分析器

我需要创建一个使用以下运算符搜索引擎解析器:

  • 苹果橙子(AND运算符)
  • 苹果OR橙子(或操作者)
  • 苹果AND NOT橙子(AND NOT运算符)
  • 苹果(行情操作)
  • 苹果AND(橙子OR(括号运算)
  • 申请*(星符)

随着一些preg_replace,我设法将字符串转换为一个数组,然后我解析这个数组以获得MySQL查询。 但我不喜欢这种方式,它非常不稳定!

我在网上搜索了一些这样做的脚本,我没有任何运气!

有人可以帮我实现这个吗?

感谢

+0

通常情况下,您首先标记输入,然后在标记化的数据上运行解析器。我的[print_r转换器](https://gist.github.com/1102761)做了类似的事情,但它具有不同的语法。 – hakre

回答

0

做你看ANTLR

+1

+1,感谢您的链接。 – hakre

-1

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

从自述:

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

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

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
+1

对于自然语言文本的基本搜索,MySQL内置的文本搜索很不错。但是,如果您想查询其他类型的文本,允许高级选项或搜索短于四个字母的单词,那么您通常必须获得更多的创意。 – Steven

+0

['IN BOOLEAN MODE'](http://dev.mysql.com/doc/refman/5.5/en/fulltext-boolean.html)几乎完全符合OP的要求,并且将最小字长设置得更低很容易。这将是一个相当简单的操作员替代。对此+1。 – Wrikken

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的工作方式

首先,您将所有db记录(或文档)添加到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*'); 

我希望我回答你的问题。