簡體   English   中英

PHP / MYSQL - 布爾全文搜索 - 精確字符串運算符(“”)在Prepared Statement和SQL Query中給出不同的結果集

[英]PHP/MYSQL - Boolean Full-Text Searches - exact string operator (“”) gives different result sets in Prepared Statement vs SQL Query

我正在我的網站上使用PHP預處理語句在高級搜索頁面上使用布爾全文搜索來查詢MySQL數據庫MyISAM表。

它非常類似於Google提供的高級搜索的第一部分,其中包含以下標准:

  • 所有這些話
  • 確切的詞或陳述(注意:這是問題所在的地方)
  • 這些話中的任何一個
  • 這些話都不是

我檢索每個輸入值,清理並處理字符串集合的每個部分,然后通過准備好的語句附加適當的信息以形成mySQL查詢。

所以本質上是針對以下搜索:

  • 全部 -
  • 確切 -
  • 任何 - 希捷東芝
  • 沒有 -

將輸出為此字符串:

seagate* toshiba*

查詢將導致如下所示:

SELECT id, description
FROM `items` 
WHERE MATCH (description)
AGAINST ('seagate* toshiba*' IN BOOLEAN MODE)

這將列出所有行,其中包含“seagate”后跟任何內容和“toshiba”,后跟描述字段中的任何內容。

這很好,輸出如下:

-(750gb*) -(320gb*) seagate* toshiba*

其中列出了上述所有行,但在說明字段中排除了“750gb”和“320gb”的所有行。

通過向“所有這些單詞”字符串添加一個值,我們將得到一個輸出:

+(16mb*) +(7200rpm*) -(750gb*) -(320gb*) seagate* toshiba*

這將列出上面的所有行,但僅顯示在描述字段中包括“16mb”和“7200rpm”的下降。

現在是有問題的部分 如果我要使用“Exact word of statement”字符串並添加值“serial ata 600”,我們將獲得以下輸出:

+(16mb*) +(7200rpm*) -(750gb*) -(320gb*) +("serial ata 600") seagate* toshiba*

使用phpmyadmin作為sql查詢運行此字符串和結果查詢我得到一個匹配搜索條件的2行結果集。

但是,當在我的網站上運行時,我得到6行的結果,這表示+(“serial ata 600”)“被完全忽略。

如果我只輸入字符串“Exact word of statement”的值,那么我們將得到一個輸出:

+("serial ata 600")

結果表明該字符串將列出包含“serial”或“ata”或“600”的所有行。

通過直接在mysql中運行相同的查詢,此結果將列出包含“serial ata 600”字樣的所有行。

此運算符MySQL定義中,它指出:

A phrase that is enclosed within double quote (“"”) characters matches 
only rows that contain the phrase literally, as it was typed.

這是MySQL中的情況,但是當使用PHP作為Prepared Statement運行相同的查詢時,返回不同的結果集。

這是准備好的聲明:

if ($result = $link->prepare("
    SELECT id, description
    FROM `items` 
    WHERE MATCH (description)
    AGAINST (? IN BOOLEAN MODE)
"))
{
    $result->bind_param("s", $pattern);
    ... ETC
}

以下是$pattern之前的輸出:

+("serial ata 600")

任何人都可能建議這種行為的原因,因為我沒有看到任何理由在PHP和MySQL之間的工作方式有任何區別。

我可以提供任何有關如何根據請求生成字符串的其他代碼,但輸出與我的示例中的相同。

任何建議/意見/輸入/反饋或評論將不勝感激。

這是一個准備好的陳述落在他們臉上的地方。 在內部,准備引擎將做相當於:

$quoted = mysql_real_escape_string('+("serial ata 600")');

這給你相當於

+(\"serial ata 600\")

現在你不再使用3個單詞的引用短語了,你發送了以下單詞:

+("serial

ata

600")

這是因為"引號是SQL元字符,你需要將它們視為元字符。但是,因為它們是元字符,准備引擎會引用它們,將它們減少到正常的簡稱引號,現在它們不再是包含您的搜索短語。它們已成為搜索短語的一部分。

不知道這是否真的有用,但你可能不得不重寫預備語句更像

... MATCH AGAINST (CONCAT('("', ?, '")'))

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM