Frage

Schnell MYSQL / PHP Frage. Ich verwende eine „nicht-so-strict“ Abfrage als Ausweich suchen, wenn keine Ergebnisse mit einer normalen Suchkriterien, nach der Melodie zu finden sind:

foreach($find_array as $word) { 
  clauses[] = "(firstname SOUNDS LIKE '$word%' OR lastname SOUNDS LIKE '$word%')";
}
if (!empty($clauses)) $filter='('.implode(' AND ', $clauses).')';
$query = "SELECT * FROM table WHERE $filter";

Nun, ich bin mit PHP, die Ergebnisse zu markieren, wie:

foreach ($find_array as $term_to_highlight){
    foreach ($result as $key => $result_string){
        $result[$key]=highlight_stuff($result_string, $term_to_highlight);
    }
}

Aber diese Methode fällt auf den Hintern, wenn ich nicht weiß, was zu markieren. Gibt es eine Möglichkeit, um herauszufinden, was das „Sound-Alike“ Spiel ist, wenn die MySQL-Abfrage ausgeführt wird?

Das heißt, wenn jemand sucht nach „Joan“ Ich will es die Option „John“ statt.

War es hilfreich?

Lösung

Die Bedingung SOUND LIKE vergleicht nur die SOUNDEX Schlüssel der beiden Wörter, und Sie können die PHP soundex () Funktion verwenden den gleichen Schlüssel zu generieren.

Wenn Sie also eine passende Zeile und benötigten gefunden, welches Wort zu markieren, um herauszufinden, können Sie sowohl den Vornamen und Nachnamen, holen und dann mit PHP zu finden, die eine Übereinstimmung und markiert nur das Wort.

Ich habe diesen Code nur dies auszuprobieren. (Hat meine Theorie xD zu testen)

<?php
// A space seperated string of keywords, presumably from a search box somewhere.
$search_string = 'John Doe';

// Create a data array to contain the keywords and their matches.
// Keywords are grouped by their soundex keys.
$data = array();
foreach(explode(' ', $search_string) as $_word) {
    $data[soundex($_word)]['keywords'][] = $_word;
}

// Execute a query to find all rows matching the soundex keys for the words.
$soundex_list = "'". implode("','", array_keys($data)) ."'";
$sql = "SELECT id, firstname, lastname
        FROM   sounds_like
        WHERE  SOUNDEX(firstname) IN({$soundex_list})
        OR     SOUNDEX(lastname)  IN({$soundex_list})";
$sql_result = $dbLink->query($sql);

// Add the matches to their respective soundex key in the data array.
// This checks which word matched, the first or last name, and tags
// that word as the match so it can be highlighted later.
if($sql_result) {
    while($_row = $sql_result->fetch_assoc()) {
        foreach($data as $_soundex => &$_elem) {
            if(soundex($_row['firstname']) == $_soundex) {
                $_row['matches'] = 'firstname';
                $_elem['matches'][] = $_row;
            }
            else if(soundex($_row['lastname']) == $_soundex) {
                $_row['matches'] = 'lastname';
                $_elem['matches'][] = $_row;
            }
        }
    }
}

// Print the results as a simple text list.
header('content-type: text/plain');
echo "-- Possible results --\n";

foreach($data as $_group) {
    // Print the keywords for this group's soundex key.
    $keyword_list = "'". implode("', '", $_group['keywords']) ."'";
    echo "For keywords: {$keyword_list}\n";

    // Print all the matches for this group, if any.
    if(isset($_group['matches']) && count($_group['matches']) > 0) {
        foreach($_group['matches'] as $_match) {
            // Highlight the matching word by encapsulatin it in dashes.
            if($_match['matches'] == 'firstname') {
                $_match['firstname'] = "-{$_match['firstname']}-";
            }
            else {
                $_match['lastname'] = "-{$_match['lastname']}-";
            }

            echo " #{$_match['id']}: {$_match['firstname']} {$_match['lastname']}\n";
        }
    }
    else {
        echo " No matches.\n";
    }
}
?>

Eine verallgemeinerte Funktion, könnte das passende soundex Wort von einem Saiten ziehen wie folgt aussehen:

<?php
/**
 * Attempts to find the first word in the $heystack that is a soundex
 * match for the $needle.
 */
function find_soundex_match($heystack, $needle) {
    $words = explode(' ', $heystack);
    $needle_soundex = soundex($needle);
    foreach($words as $_word) {
        if(soundex($_word) == $needle_soundex) {
            return $_word;
        }
    }
    return false;
}
?>

Welche, wenn ich es bin zu verstehen, könnte richtig, in bis dahin erbrachten Code verwendet werden, wie:

foreach ($find_array as $term_to_highlight){
    foreach ($result as $key => $result_string){
        $match_to_highlight = find_soundex_match($result_string, $term_to_highlight);
        $result[$key]=highlight_stuff($result_string, $match_to_highlight);
    }
}

Das wäre nicht so effizient tho sein, da der gezieltere Code im ersten Schnipsel.

Andere Tipps

Beachten Sie, dass SOUNDS LIKE nicht funktioniert, wie Sie denken, es tut. Es ist nicht gleichbedeutend mit LIKE in MySQL, da sie nicht die % Platzhalter nicht unterstützt.

Dies bedeutet, dass Ihre Abfrage wird nicht „John David“ finden, wenn für „John“ gesucht. Dies könnte akzeptabel sein, wenn dies nur Ihr Rückfall, aber es ist nicht ideal.

So, hier ist ein anderer Vorschlag (das könnte Notwendigkeit Verbesserung); erster Einsatz PHPs soundex() Funktion die soundex des Schlüsselwort zu finden, die Sie suchen.

$soundex = soundex($word);
$soundexPrefix = substr($soundex, 0, 2); // first two characters of soundex
$sql = "SELECT lastname, firstname ".
    "FROM table WHERE SOUNDEX(lastname) LIKE '$soundexPrefix%' ".
    "OR SOUNDEX(firstname) LIKE '$soundexPrefix%'";

Nun wird eine Liste von Vornamen und lastnames haben, die eine vage Ähnlichkeit hat in klingender (dies könnte eine Menge Einträge vorhanden sein, und man könnte die Länge der soundex Präfix verwenden Sie für Ihre Suche erhöhen möchten). Sie können dann die Levenshtein Abstand zwischen dem soundex jedes Wort berechnen und Ihren Suchbegriff und sortieren Sie nach, dass.

Zweitens Sie parametrisierte Abfragen in MySQL zu vermeiden, SQL-Injection-Fehler aussehen sollten.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top