Подтвердить что ты не робот

Левенштейн: MySQL + PHP

$word = strtolower($_GET['term']); 

$lev = 0;

$q = mysql_query("SELECT `term` FROM `words`"); 
while($r = mysql_fetch_assoc($q)) 
{ 
    $r['term'] = strtolower($r['term']); 

    $lev = levenshtein($word, $r['term']);

    if($lev >= 0 && $lev < 5)
    {
        $word = $r['term'];
    }
}

Как я могу переместить все это только в один запрос? Не нужно запрашивать все термины и выполнять фильтрацию на PHP.

4b9b3361

Ответ 1

Вам нужна функция levenshtein в MySQL и запрос типа

$word = mysql_real_escape_string($word);
mysql_qery("SELECT `term` FROM `words` WHERE levenshtein('$word', `term`) BETWEEN 0 AND 4");

Ответ 2

Существует два способа реализации функции Levenshtein в MySQL. Во-первых, необходимо создать ЗАПОМИНУЮ ФУНКЦИЮ, которая работает так же, как НЕПРАВИЛЬНАЯ ОПЕРАЦИЯ, за исключением того, что она имеет различные входы и выход. Это хорошо для небольших наборов данных, но немного медленнее на чем-то, приближающемся к нескольким тысячам строк. Вы можете найти более подробную информацию здесь: http://kristiannissen.wordpress.com/2010/07/08/mysql-levenshtein/

Второй метод - реализовать пользовательскую функцию в C/С++ и связать ее с MySQL как разделяемой библиотекой (*.so файл). Этот метод также использует STORED FUNCTION для вызова библиотеки, что означает, что фактический запрос для этого или первого метода может быть идентичным (при условии, что входы для обеих функций одинаковы). Подробнее об этом методе можно узнать здесь: http://samjlevy.com/mysql-levenshtein-and-damerau-levenshtein-udfs/

С помощью любого из этих методов ваш запрос будет выглядеть примерно так:

SELECT term FROM words WHERE levenshtein(term, 'term') < 5;

Кроме того, помните, что значение "пороговое значение" должно изменяться относительно исходной длины слова. Лучше подумать об этом с точки зрения процентного значения, т.е. Половина вашего слова = 50%, половина "члена" = 2.

Ответ 3

Если у вас есть огромная база данных, вы можете сначала фильтровать слова, используя SOUNDEX:

$word = strtolower(mysql_real_escape_string($_GET['term']));

$rs = mysql_query("SELECT LOWER(`term`) FROM `words` WHERE SOUNDEX(term) = SOUNDEX(" . $word . ")");

while ($row = mysql_fetch_assoc($rs)) { 

    $lev = levenshtein($word, $row['term']);

    ....

}

Если у вас достаточно времени, чтобы играть с расширением или процедурой C, вы можете достичь более высокой производительности, но фильтрация записей на mysql перед применением реального levenshtein сделает вещи быстрее без особых усилий.

Ответ 4

Если вы имеете дело с очень большими наборами данных, я обнаружил, что гораздо эффективнее обрабатывать операции Levenshtein и сортировать их в PHP, чем в MySQL. например запрос около 1000 записей:

MySQL (~ 0.0050s) → PHP Levenshtein (~ 1.300s)

против.

MySQL Levenshtein ( >= 5.000s) → PHP (~ 0.250s)

Существует также множество других вариантов оптимизации поисковых систем, но если вы хотите использовать Levenshtein, просто отдавайте себе отчет в данных, которые вы будете обрабатывать, и о задержках, которые вы хотите.

Ответ 5

Вы можете сделать этот код немного более аккуратным, но @profitphp прав, вы не можете делать это в MySQL без библиотеки levenstein.

$word = strtolower($_GET['term']);

$q = mysql_uqery("SELECT LOWER(`term`) FROM `words`");

while($r = mysql_fetch_assoc($q)) { 

    $lev = levenshtein($word, $r['term']);

    ....

}

Ответ 6

Я предлагаю вам включить вызов levenshtein (ссылка: http://www.artfulsoftware.com/infotree/queries.php#552)  в ваш запрос.

Вы должны использовать mysqli_query ($ q), потому что mysql_query ($ q) устарел и могут быть удалены в будущих версиях PHP!

$word = mysql_real_escape_string($word);
$query = "SELECT `term` FROM `words` WHERE levenshtein('$word', `term`)   BETWEEN 0 AND 4";
mysqli_qery($query);

Ответ 7

Я делаю это в Oracle, реализуя алгоритм в PL/SQL внутри функции, которая может быть вызвана.

Ответ 8

Это один запрос. Если вы спрашиваете, можете ли вы переместить функциональность levenshtein в mysql, вы не сможете.

Хорошо, хорошо, но это не легче, чем просто делать это в php.

http://www.artfulsoftware.com/infotree/queries.php?&bw=1280#552