Как осуществить поиск неточных совпадений по MySQL?
Приветствую!
Как осуществить подобного рода поиск по MySQL и реально ли это вообще?
Строка поиска: г Санкт-Петербург, тер Авиагородок
Строка в таблице: Авиагородок, Санкт-Петербург
Строка поиска: г Санкт-Петербург, тер. снт Торики
Строка в таблице: Торики, Красносельский р-н, Санкт-Петербург
Строка поиска: г Санкт-Петербург
Строка в таблице: Санкт-Петербург
Строка поиска: г Москва, Воскресенское п, п Воскресенское
Строка в таблице: Воскресенское поселение, Московская обл.
Плюс, нужно ранжировать - при запросе г Москва результат Москва должен иметь приоритет над результатами Десеновское, Москва и Бутово Южное, Москва.
И т. п., записей около 16 тыс., поиск производится один раз на каждого уника (проект не хайлоад, нишевый интернет-магазин).
Пробовал колдовать с FULLTEXT-поиском, но пока ничего дельного не вышло.
Рассматривается применение сторонних модулей - Sphinx, Elastic, может, даже nosql базы для каких-то промежуточных операций, но рабочей БД проекта является именно MySQL.
Сейчас главное - понять, в какую сторону копнуть.
Всем спасибо, в итоге удалось написать свой алгоритм, основанный на простых условиях и утверждении, что сегменты адреса в наших данных находятся в обратном порядке относительно исходного адреса.
Запрос разбивается по запятым, вырезаются все типы (р-н, район, обл, АО, г, поселок, хутор, снт и .п.), "разворачивается", затем последовательно производится поиск: город+район+регион, город+регион, город. Поиск останавливается на уровне, на котором появился результат.
в Мускуле таких чудесов нету, быть не может, и появится не раньше лет через 15
копайте в стороу как Убер, 2GIs и тот же Яндекс решают эту проблему, если по взрослому ( всякие Entity namig recogntion, Тамита парсер, вектора на стеммированых ковордах и т.п.)
по-детски можно составить алгоритмичеки ( с элементами взрослого) таблицу нормализации:
п Воскресенское =>Воскресенское поселение
Воскресенское п =>Воскресенское поселение
Жаль. Проект далеко не масштаба Убер или 2GIS, такие решения ему не по карману. Но Томита стоит просто поковырять, спасибо за наводку.
По-детски - это пока действительно все, что приходит в голову :(
Возможно вам поможет "нормализация" от различных сторонних API, аля dadata. На вашей стороне хранить нормализированный вариант, а через API dadata приводить к нормальному виду запрос от клиента.
Александр, ДаДата временами отрезает части запроса, но не сообщает об этом, и, к тому же, часто выдает слишком подробный адрес, вплоть до улицы и дома.
Решение описал в самом вопросе, внизу.
Далее по условиям просто формирую запросы типа:
SELECT * FROM dadata_addresses WHERE `source` LIKE 'Алхимово%' AND `source` LIKE '%Московская%'
Александр, данная таблица разрастаться точно не будет. К тому же, скорее всего, это временное решение. Потому что сам список будет оптимизироваться.
zhaar, в основном не получилось из-за такого: Осиновая Роща, Санкт-Петербург = г Санкт-Петербург, п Парголово, ул Осиновая (Осиновая Роща) - Дадата при возможности дает слишком подробные для моей задачи данные.
Так же встречается отсечение части адресов без уведомления о возможных проблемах (приходит статус "Адрес распознан уверенно"). Но над этим уже пообещали поработать сами дадатовцы.
Ну, так и рассматривайте зрелые модули поиска, а не изобретение велосипедов, которые все равно будут неудачнее, да еще и потребуют больше времени на поддержку и доработки.
Теоретически вроде бы и работы немного: разобрать тексты, в которых будешь искать, на базу ключей и искать по ним... но практически тот же Сфинкс это уже умеет делать без танцев с бубном, а что вам еще надо?
Я как раз и упомянул Sphinx как возможное решение, но, увы, не работал с ним раньше. Поэтому и хотел уточнить у более опытных коллег, действительно ли он поможет справиться с поставленной задачей.
Так вот, если без воды и по делу, то какие методы/флаги/опции нужно скомбинировать, чтобы получить необходимый результат?
Stalker_RED, а угадывать не надо, я несколько примеров привел. Они четко показывают характер совпадения всех 15800 строк. Если примерно представляете, как это обработает Сфинкс, набросайте немного. Буду благодарен.
MikUrrey, вообще-то с адресами есть еще один метод работы - по КЛАДР / ФИАС.
Но, например, Почта России при всех имеющихся у нее базах адресов при приведении произвольной строки к адресу временами лажает зверски. И Яндекс на своих картах - тоже.
А Сфинкс вам будет находить не совсем то, что вам надо, а то, что похоже по содержанию ключей. Скорее всего, на многие запросы будет несколько ответов, похожих по тексту. Находится ли это похожее хотя бы в одной области с искомым - это вам никакой современный ИИ не скажет....
Adamos, а мы попробовали сперва прогнать список через ДаДату. И даже их платный сервис "Стандартизация адресов" справился на троечку с минусом, а цель была - как раз связать табличку по ФИАС ID с их же данными от метода detectAddressByIp.
MikUrrey, по произвольно написанному адресу - это задача принципиально нерешаемая.
С ней и человек-то на сто процентов не справляется, куда там компьютеру.