Se podría considerar el uso de la clase Doctrine Inflector en conjunción con un stemmer para esto.
Aquí es el algoritmo en un nivel alto
- de Split cadena de búsqueda en los espacios, las palabras de proceso individual
- minúsculas la palabra de búsqueda
- eliminar caracteres especiales
- singularizan, reemplace differing portion con comodín (' % ')
- Vástago, reemplace la porción diferente con comodín ('% ')
Ésta es la función que armó
/**
* Use inflection and stemming to produce a good search string to match subtle
* differences in a MySQL table.
*
* @string $sInputString The string you want to base the search on
* @string $sSearchTable The table you want to search in
* @string $sSearchField The field you want to search
*/
function getMySqlSearchQuery($sInputString, $sSearchTable, $sSearchField)
{
$aInput = explode(' ', strtolower($sInputString));
$aSearch = [];
foreach($aInput as $sInput) {
$sInput = str_replace("'", '', $sInput);
//--------------------
// Inflect
//--------------------
$sInflected = Inflector::singularize($sInput);
// Otherwise replace the part of the inflected string where it differs from the input string
// with a % (wildcard) for the MySQL query
$iPosition = strspn($sInput^$sInflected, "\0");
if($iPosition !== null && $iPosition < strlen($sInput)) {
$sInput = substr($sInflected, 0, $iPosition) . '%';
} else {
$sInput = $sInput;
}
//--------------------
// Stem
//--------------------
$sStemmed = stem_english($sInput);
// Otherwise replace the part of the inflected string where it differs from the input string
// with a % (wildcard) for the MySQL query
$iPosition = strspn($sInput^$sStemmed, "\0");
if($iPosition !== null && $iPosition < strlen($sInput)) {
$aSearch[] = substr($sStemmed, 0, $iPosition) . '%';
} else {
$aSearch[] = $sInput;
}
}
$sSearch = implode(' ', $aSearch);
return "SELECT * FROM $sSearchTable WHERE LOWER($sSearchField) LIKE '$sSearch';";
}
Qué me encontré con varias cadenas de prueba
Input String: Mary's Hamburgers
SearchString: SELECT * FROM LIST2 WHERE LOWER(some_field) LIKE 'mary% hamburger%';
Input String: Office Supplies
SearchString: SELECT * FROM LIST2 WHERE LOWER(some_field) LIKE 'offic% suppl%';
Input String: Accounting department
SearchString: SELECT * FROM LIST2 WHERE LOWER(some_field) LIKE 'account% depart%';
Probablemente no es perfecto, pero es un buen comienzo de todos modos! Donde caerá es cuando se devuelven múltiples coincidencias. No hay lógica para determinar la mejor coincidencia. Ahí es donde entran cosas como MySQL fulltext y Lucene. Pensando en ello un poco más, ¡usted podría ser capaz de usar levenshtein para clasificar múltiples resultados con este enfoque!
Sé que este es un hilo antiguo, pero acabo de agregar una respuesta, mira lo que piensas si tienes un minuto. – quickshiftin