2011-07-29 271 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*'); 

我希望我回答你的問題。