Левенштейн: 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.

Solutions Collecting From Web of "Левенштейн: MySQL + PHP"

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

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

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

Второй способ – реализовать пользовательскую функцию в C / 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.

Если у вас есть огромная база данных, вы можете сначала фильтровать слова, используя 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 сделает вещи быстрее без особых усилий.

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

MySQL (~ 0.0050s) -> PHP Levenshtein (~ 1.300s)

против

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

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

Вы можете сделать этот код немного более аккуратным, но @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']);

     ....

 }

Я предлагаю вам включить вызов 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); 

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

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

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

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