【问题标题】:Search Engine Keywords Parser搜索引擎关键字解析器
【发布时间】:2011-10-15 21:20:43
【问题描述】:

这是我想做的:

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

  • 苹果 AND 橙子(AND 运算符)
  • 苹果 OR 橙子(OR 运算符)
  • 苹果 AND NOT 橙子(AND NOT 运算符)
  • " Apples "(引号运算符)
  • Apples AND ( Oranges OR Pears )(括号运算符)
  • Appl*(明星运营商)

通过一些 preg_replace,我设法将字符串转换为数组,然后解析该数组以获取 MySQL 查询。 但我不喜欢这样,而且很不稳定!

我在网上搜索了一些执行此操作的脚本,但我没有任何运气!

有人可以帮我实现吗?

谢谢

【问题讨论】:

  • 通常您首先对输入进行标记化,然后对标记化数据运行解析器。我的print_r converter 做了类似的事情,但是语法不同。

标签: php operators search-engine text-parsing


【解决方案1】:

你看过ANTLR

【讨论】:

    【解决方案2】:

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

    来自自述文件:

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

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

    【讨论】:

      【解决方案3】:

      您可以自制类似以下内容(重要提示: $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);
      }
      

      【讨论】:

        【解决方案4】:

        【讨论】:

        • MySQL 内置的文本搜索很好,用于自然语言文本的基本搜索。但是,如果您想查询其他类型的文本、允许高级选项或搜索少于四个字母的单词,那么您通常需要更有创意。
        • IN BOOLEAN MODE 几乎完全符合 OP 的要求,并且将最小字长设置得更低非常容易。这将是一个非常简单的操作符替换。对此 +1。
        【解决方案5】:

        好的,这将是一个很大的答案。

        我认为您需要的是解析器生成器。一种根据给定语法生成代码以解析文本的软件。这些解析器通常有两个主要组件:词法分析器和解析器。词法分析器识别 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*');
        

        希望我回答了你的问题。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2011-09-21
          • 1970-01-01
          • 2011-07-24
          • 2012-10-30
          • 1970-01-01
          • 1970-01-01
          • 2011-08-24
          相关资源
          最近更新 更多