PHP - возвращает ближайшее совпадение из базы данных

Я возвращаю данные мобильного телефона на основе пользовательского агента. Но в случае, когда пользовательский агент не хранится (более новая версия телефона или программного обеспечения), я хочу иметь возможность вернуть ближайшее совпадение, немного похожее на то, как Google отображает «вы имели в виду это». то есть

если у меня есть сохраненный пользовательский агент

Mozilla/5.0 (Linux; U; Android 2.1-update1; en-nl; Desire_A8181 Build/ERE27) AppleWebKit/530.17 (KHTML, например Gecko) Version/4.0 Mobile Safari/530.17

и используемый пользовательский агент

Mozilla/5.0 (Linux; U; Android 2.1-update1; en-nl; Desire_G45H Build/ERE27) AppleWebKit/530.17 (KHTML, как Gecko) Version/4.0 Mobile Safari/530.17

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

Кто-нибудь знает способ добиться этого?


person Phil Jackson    schedule 08.07.2011    source источник
comment
Если вы хотите разработать свою собственную систему, я согласен, но.... Вы взглянули на docs.php.net/function.get_browser и обычно быстро обновляющийся файл browscap.ini по адресу browsers.garykeith.com/downloads.asp ?   -  person VolkerK    schedule 08.07.2011
comment
Если вы хотите позаботиться об этом только на уровне базы данных, вам следует удалить тег php.   -  person user247702    schedule 08.07.2011


Ответы (5)


использовать полнотекстовый поиск с наиболее релевантными данными...

SELECT * MATCH(browser) AGAINST ('your browser') AS score order by score DESC
person Avinash    schedule 08.07.2011
comment
Интересно, нужно ли было бы использовать ограничение, хотя правильно, поскольку оно все равно вернет все результаты по порядку? Будет демонстративно смотреть в это. - person Phil Jackson; 08.07.2011
comment
Имейте в виду, однако, что полнотекстовый индекс MySQL — зверь с некоторыми проблемами — например, минимальная длина слова составляет 4 символа: в 530.17 он автоматически всегда будет игнорировать часть .17. Кроме того, критерий ближайшего соответствия немного ошибочен. Это хорошо работает для естественных текстов, но, возможно, не для пользовательских агентов. - person Steffen Müller; 08.07.2011
comment
вы можете изменить минимальную длину слова и отключить стоп-слова, что является еще большей проблемой. см. dev.mysql.com/doc/refman/5.1 /ru/fulltext-fine-tuning.html - person user428517; 21.02.2013

Обычным подходом к нечеткому сопоставлению строк являются такие вещи, как вычисление расстояния Левенштейна или реализация его в виде индекса поиска n-грамм. Но для сопоставления пользовательских агентов это излишне.

Скорее уменьшите строку, которую вы ищете, до определенных важных критериев, а затем сделайте что-то вроде

SELECT * FROM agents WHERE agent LIKE "Mozilla/5.0 (Linux; U; Android%) AppleWebKit/5% Version/4.0 Mobile Safari/5%"

Итак, вы вырезаете некоторые слишком подробные части и заменяете их на % в своем утверждении LIKE. Однако вам следует пересмотреть архитектуру - я бы сохранил только важные части и не указал точный номер сборки и т. д. Также рассмотрите возможность использования внешней библиотеки, которая уже содержит пользовательские агенты и выполняет сопоставление для вас, нет необходимости изобретать велосипед.

РЕДАКТИРОВАТЬ: как указал VolkerK выше, "внешняя библиотека" должна быть PHPs getbrowser. Просто добавлено для полноты ответа ;-)

person Steffen Müller    schedule 08.07.2011
comment
У меня есть база данных из 6 549 мобильных устройств с несколькими пользовательскими агентами против них, я не изобретаю велосипед, просто сглаживаю края. Спасибо за вышеописанный метод, попробую. С уважением - person Phil Jackson; 08.07.2011

Взгляните на один из сценариев на Выделите разницу между двумя строками в PHP, с некоторыми изменениями вы сможете получить процент разницы.

person user247702    schedule 08.07.2011
comment
Это две строки, я мог бы написать для этого свою собственную функцию или использовать levenshtein(), но это вопрос эффективности sql, и мне было интересно, есть ли эквивалент sql - person Phil Jackson; 08.07.2011

Используйте полнотекстовый поиск; в противном случае эти функции могут помочь:

person seriousdev    schedule 08.07.2011
comment
опять же, я не хочу выбирать каждую строку пользовательского агента из моей базы данных и сравнивать, это неэффективно. - person Phil Jackson; 08.07.2011

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

проверьте эти функции

SIMILAR_TEXT

SOUNDEX

ЛЕВЕНШТЕЙН

I.E.

$most_similar = "";
$highestPercentage = 0;
foreach ($ua in $all_user_agents) {
    $i = similar_text($current_user_agent, $ua, &$p);
    if ($p > $highestPercentage) {
        $highestPercentage = $p;
        $most_similar = $ua;
    }
}

echo "most similar = $most_similar"

В любом случае, вы можете использовать полнотекстовый поиск mySQL, следуя некоторым рекомендациям, таким как это один

person VAShhh    schedule 08.07.2011