mySQL - 匹配拉丁(英语)表单输入到utf8(非英语)数据

时间:2014-10-03 19:03:20

标签: php mysql regex search levenshtein-distance

我在mySQL中维护一个音乐数据库,如何返回存储在例如mySQL中的结果当人们搜索'Tiesto'时,'Tiësto'?

所有数据都存储在全文索引中,如果这有任何区别的话。

我已经在PHP中使用Levenshtein和在SQL中使用REGEXP - 而不是试图解决这个问题,而只是为了增加可搜索性。

PHP:

function Levenshtein($word) {

$words = array();
for ($i = 0; $i < strlen($word); $i++) {
    $words[] = substr($word, 0, $i) . '_' . substr($word, $i);
    $words[] = substr($word, 0, $i) . substr($word, $i + 1);
    $words[] = substr($word, 0, $i) . '_' . substr($word, $i + 1);
    }
$words[] = $word . '_';
return $words;
}

$fuzzyartist = Levenshtein($_POST['searchartist']);
$searchimplode = "'".implode("', '", $fuzzyartist)."'";

MySQL的:

SELECT *
FROM new_track_database
WHERE artist REGEXP concat_ws('|', $searchimplode);

要添加,我经常在PHP中执行字符集转换和字符串卫生,但这些一直是其他方式 - 标准化非拉丁字符。我无法理解执行oppsite流程,但仅在某些情况下才会根据我存储的数据。

1 个答案:

答案 0 :(得分:1)

一种可能的解决方案是在“艺术家”旁边的数据库中创建另一列,例如“artist_normalized”。在这里,在填充表时,您可以插入字符串的“规范化”版本。然后可以对artist_normalized列执行搜索。

测试代码:

<?php
$transliterator = Transliterator::createFromRules(':: NFD; :: [:Nonspacing Mark:] Remove; :: NFC;', Transliterator::FORWARD);
$test = ['abcd', 'èe', '€', 'àòùìéëü', 'àòùìéëü', 'tiësto'];
foreach($test as $e) {
    $normalized = $transliterator->transliterate($e);
    echo $e. ' --> '.$normalized."\n";
}
?>

结果:

abcd --> abcd
èe --> ee
€ --> €
àòùìéëü --> aouieeu
àòùìéëü --> aouieeu
tiësto --> tiesto

魔术是由Transliterator类完成的。指定的规则执行三个操作:分解字符串,删除变音符号,然后重新组合字符串,规范化。 PHP中的Transliterator是建立在ICU之上的,所以这样做依赖于ICU库的表格,这些表格完整可靠。

注意:此解决方案需要PHP 5.4或更高版本,并带有 intl 扩展名。