| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > СУБД, общие вопросы > Нужны правильный FullText & geo search |
| Автор: kami 21.11.2014, 22:59 |
| Здравствуйте, уважаемые! Есть база... пусть будет с адресами, тем более что пока так и есть (улицы и дома) + их координаты. Нужно: искать в базе по адресам (пример - подсказки Яндекс.Карт и 2ГИС при вводе адреса) и по координатам (найти ближайшие записи к указанной в запросе точке) Что пробовали: 1. MySQL. поиск адреса проходит великолепно, к примеру запрос "11* лини*" с легкостью и правильно находит в числе первых "10-11 линии В.О.", "11-я Красноармейская линия" и т.п. Причем - можно задавать вес каждому слову в запросе, используя "<", ">". Но с поиском ближайших к точке - плохо, геопространственный индекс используется только с функциями "входит/не входит в прямоугольник", а при определении гео-дистанции перебирается полностью таблица. 2. MongoDB. Здесь отлично и очень быстро отрабатывает поиск ближайших. А вот с полнотекстовым какая-то беда. Во-первых, поиск регистро-зависимый. Во вторых - поиск по "Красно" выдает адреса типа "Краснопутиловская ул." (+ дома на этой улице), "Красная ул." и т.п. А вот запрос "Красноп" уже не выдает вообще ничего. И это "ничего" продолжается до ввода "Краснопутиловск". Имхо, нелогично как-то. 3. Postgre. Ситуация аналогична Монге, такое ощущение, что используется один и тот же движок. Попытки настроить индекс на pg_catalog.simple FTS (взамен pg_catalog.russian) не привели к успеху - "индекс не поддерживается на utf-8 строках". Вопрос: есть ли что-нибудь, что совмещает: - простоту полнотекстового поиска MySQL (я подозреваю, что там "неправильный" FTS, а правильный как раз у Mongo и Postgre, но нам он подходит идеально) - поиск ближайших к указанной точке. В коллекциях гарантированно будут только координаты типа POINT и запрашиваться будут в 99% именно "ближайшие к вот такой точке". Возможно, я неправильно настроил поиск в постгресе или монге. Но, к сожалению, не нашел таких настроек... буду рад, если поделитесь ссылкой. |
| Автор: tzirechnoy 23.11.2014, 17:05 |
| Про постгрэсс: так преобразуй его в cp1251 и lower case. Можно -- дажэ не выделяя какого-то поля, прямо в индэксе (только в запросах -- те жэ функцыи, разумеется, должны быть). |
| Автор: tzirechnoy 24.11.2014, 14:28 |
| А можно конкретный пример индэкса и запроса, как это получилось? |
| Автор: tzirechnoy 24.11.2014, 15:05 | ||
А, кстати понял, да. Надо запросы на начало через :* выделять.
|
| Автор: kami 24.11.2014, 15:17 | ||||||
| tzirechnoy, да, конечно. Я подозреваю, что просто не умею готовить Postgres. Тестовая база, примерно 11 тыс. записей. Исходная таблица (скрипт скопирован из pgAdmin, "лишние" поля удалил):
После чего - создан индекс:
Ну и собственно - запрос:
Вот по этому запросу ничего не находит. А по запросу "Краснопутиловск" - находит правильную улицу - "Краснопутиловская". Моя нипанимать, в чем дело... Добавлено через 1 минуту и 54 секунды Upd: пока писал, не увидел ответ выше Пробую... Добавлено через 10 минут и 28 секунд Ткните в меня ссылкой на документацию, пожалуйста, где описаны вот такие вот маски для поиска, а то я так долго буду тыкаться, как слепой котенок С "Красноп:*" отрабатывает отлично, а вот с другим запросом "11:* лини:*" - ошибка синтаксиса. Теоретически, он должен находить улицы типа "11-я линия В.О.", "11-я Красноармейская линия" и т.п. Т.е. - в одном запросе - 2 начала слов для поиска. |
| Автор: tzirechnoy 24.11.2014, 17:34 |
| Потому, что to_tsquery('russian', '11:* & лини:*') http://www.postgresql.org/docs/9.3/static/textsearch-controls.html#TEXTSEARCH-PARSING-QUERIES Там ещё ссылка на секцыю 8.11 -- тожэ полезная. |
| Автор: kami 24.11.2014, 20:46 | ||||||||||
| tzirechnoy, спасибо. Относительно понятнее стало, почему так происходит. Все-таки поведение отличается от того, что мне необходимо. В частности:
выдает
Т.е. он считает, что 10-11 - это одна лексема (или как там они называются)... Даже если сделать так:
то выдается
Как результат - искомые "10-11 линии" оказываются далеко-далеко по ранжированию на запрос типа
А вот MySQL разбивает на лексемы так, как в нашем случае нужно - "10" "11" "В.О." "линии". Вернее, я считаю, что у него не используются лексемы как таковые, а просто разбиение на слова... Что я продолжаю делать не так? |
| Автор: tzirechnoy 25.11.2014, 00:55 | ||
Ну, он, очевидно, не матчит 11. Если Вы думаете, что - у вас безсмысленнен -- то замените минусы на пробелы. Заодно, кстати, и lower() сделайте. Ну и, надо долго медитировать, конечно, по вопросу -- подходит вам встроенный русский словарь или лучшэ без него или лучшэ как-то его изменить. |
| Автор: kami 27.11.2014, 23:08 |
| Прошу прощения за долгое молчание. Ну, собственно, вопрос можно закрывать. Путем долгих терзаний и сомнений между Монгой и Постгресом, был выбран Постгрес. Не последнюю роль в этом процессе сыграла монетка, которая легла орлом вверх Бесспорных аргументов "за", по большому счету не было: в обеих системах обеспечить необходимый нам вид поиска можно только с дополнительными извратами. Плюсом Постгреса стала возможность использовать маску ":*", у Монги такого не нашел :(. А жаль, ибо на ней уже крутятся логи многих сервисов и очень хорошо себя чувствуют... Подводя итог: в таблицах для обеспечения FTS будут созданы "нормализованные" поля, содержащие вместо всех знаков препинания - пробелы, все буквы - в одном регистре (без разницы - нижний или верхний, емнип, выбрали нижний). Эти поля будут заполняться программно, а не средствами СУБД. Дополнительно - рядом с ними будут поля типа ::tsvector (шаблон simple) (правда, моя нипанимать - зачем это надо, неужто полнотекстовый индекс, созданный по "нормализованному полю" - на самом деле не индекс?) Полагаю, все следующие вопросы пойдут уже в профильный раздел. Еще раз спасибо. |
| Автор: tzirechnoy 27.11.2014, 23:43 | ||||
А зачем? Всё равно ведь большынство БД -- IO-bound, смысл увеличивать количество данных на диске, экономя на преобразовании "на лету"? Добавлено через 48 секунд
Моя тожэ. Добавлено через 1 минуту и 19 секунд В смысле -- я совершэнно непонимаю, зачем тебе это понадобилось и почему ты считаешь, что это поле что-нибудь изменит. |
| Автор: tzirechnoy 28.11.2014, 00:57 | ||||
| А, я кажэтся понял. Вы не увидел postgres function index http://www.postgresql.org/docs/9.3/static/indexes-expressional.html. Так вот, они здесь есть. И можно писать что-то вроде
При поиске, конечно, надо будет всегда указывать ровно те жэ функцыи, т.е.:
|
| Автор: kami 29.11.2014, 15:40 |
Кошмар какой Примерно такие же непонятки я испытывал, когда узнал, что у MySQL на каждый чих задается своя кодировка. |