SQL Full Text Search liefert zu viele Ergebnisse

felsi

Banned
Registriert
Mai 2007
Beiträge
556
Hallo,

ich versuche gerade eine Full Text Search in MySQL zu erstellen. Das hat soweit auch gut funktioniert. Wenn ich meine Query direkt in SQL teste, erhalte ich die gewünschten Ergebnisse. Zum Beispiel:

Code:
SELECT id, artikelnummer, name FROM products WHERE MATCH (artikelnummer, name) AGAINST ("+suchwort1+suchwort2" IN BOOLEAN MODE)

Leider funktioniert die Abfrage jedoch nicht wie gewünscht, wenn ich meine daraus erstellte JSON abrufen möchte. Ich bekomme die Suchwörter per GET aus der URL (das ganze natürlich per PDO):

Code:
// Create query
    $query = 'SELECT id, artikelnummer, name FROM products WHERE MATCH (artikelnummer, name) AGAINST (:term IN BOOLEAN MODE)';

    // Prepare statement
    $stmt = $this->conn->prepare($query);

    // Bind term
    $stmt->bindParam(':term', $this->term);;

    // Execute query
    $stmt->execute();

    return $stmt;

Rufe ich nun also

URL/search.php?term=suchwort1 suchwort 2

auf erhalte ich Ergebnisse, in denen sowohl "suchwort1" als auch "suchwort2" vorkommen. Ich möchte aber natürlich, wie in meiner SQL Abfrage ganz oben, nur Ergebnisse, in denen beide Suchworte vorkommen.

Selbst wenn ich folgende URL aufrufe

URL/search.php?term=+suchwort1 +suchwort 2

liefert es mir Ergebnisse mit suchwort1 ODER suchwort2 zurück.

Gibt es eine Möglichkeit, den AND Operator (+) direkt in den :term zu integrieren?

Vielen Dank schon mal
 
Und was übergibst du der Datenbank konkret? Lass dir :term mal ausgeben.

Stichwort URL Encoding...
 
  • Gefällt mir
Reaktionen: NMA und SomeDifferent
Yuuri schrieb:
Stichwort URL Encoding...

Ja, daran habe ich schon gedacht. Habe mir :term nun mal ausgeben lassen und es wird tatsächlich nicht +suchwort1 und +suchwort2 übergeben, sondern eben ohne den + Operator, also "suchwort1 suchwort2"

Aber wie löse ich das nun?
 
felsi schrieb:
Aber wie löse ich das nun?
Du musst die Parameter eben korrekt in der URL übergeben - aus +wort1+wort2 wird dann eben %2Bwort1%2Bwort2, siehe (raw)urlencode(). Allerdings ist es extrem fragwürdig direkt SQL per URL übergeben zu lassen. Übergib deine Wörter oder deine eigene, sichere DSL per URL und überführ sie dann in konkretes SQL.
 
  • Gefällt mir
Reaktionen: NMA
Yuuri schrieb:
Übergib deine Wörter oder deine eigene, sichere DSL per URL und überführ sie dann in konkretes SQL.

Da fehlt mir gerade der Ansatz dazu? Hast du einen Link o.ä, wo ich mich dazu einlesen kann?
Danke

Edit: Falls das der Ansatz ist:

Wenn ich mein stmt zu

Code:
   $stmt->bindValue(':term', '%2B ' . $this->term . '%2B ');

ändere, wird trotzdem nur "suchwort" übergeben.
 
Zuletzt bearbeitet:
Wenn ich das richtig seh, hast Du die doppelten “ um den Term vergessen.

FTS ist kein SQL, da wird’s syntaktisch immer komisch.

Re: dem Plus, vor der Übergabe an PDO den Suchterm per preg_replace oä nach word-delimiter left durchsuchen und den durch ein + ersetzen. Hab leider grad nicht auf dem Schirm, was PCRE da verlangt. \b geht immer, aber das paßt auf Wortanfang UND Ende, ist also umständlicher.
 
  • Gefällt mir
Reaktionen: NMA
RalphS schrieb:
Wenn ich das richtig seh, hast Du die doppelten “ um den Term vergessen.

Code:
    $stmt->bindValue(':term', "'%2B' . $this->term . '%2B'");

Das bringt mich tatsächlich ein Stück näher ans Ziel. Was jetzt passiert ist, dass es mir zuerst die tatsächlich gewünschten Ergebnisse liefert (also alles zu suchwort1 UND suchwort2). Danach kommen dann allerdings Ergebnisse, die sowohl suchwort1 als auch suchwort2 beinhalten. Auch ein seltsames verhalten, das ich direkt per SQL überhaupt nicht nachvollziehen kann.

Edit: Stimmt doch nicht. Das ist das einfache Ergebnis aus: "suchwort1 suchwort2".

Re: dem Plus, vor der Übergabe an PDO den Suchterm per preg_replace oä nach word-delimiter left durchsuchen und den durch ein + ersetzen. Hab leider grad nicht auf dem Schirm, was PCRE da verlangt. \b geht immer, aber das paßt auf Wortanfang UND Ende, ist also umständlicher.

Habe auch schon daran gedacht, das Leerzeichen zwischen den Worten im Suchterm mit einem + zu ersetzen. Da komme ich allerdings nicht wirklich weiter, weil ich nicht weiß, an welcher Stelle ich da ansetzen muss. Kannst du mir da noch mal auf die Sprünge helfen? Danke

Edit: Ok, ich kann nun direkt den Term in der URL modifizieren (ich weiß nicht, ob das richtig ist):

Code:
$products->term = isset($_GET['term']) ? preg_replace('/(\w+)/', '+$1', $_GET['term']) : die();

Das funktioniert, jedoch hab eich noch das Problem, dass auch nach Umlauten ein + gesetzt wird..

Edit: Ok, habs. Falls es mal jemand braucht:
$products->term = isset($_GET['term']) ? preg_replace('/(\w+)/u', '+$1', $_GET['term']) : die();
 
Zuletzt bearbeitet:
Zurück
Oben