Модераторы: LSD
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Нужны правильный FullText & geo search, какую СУБД взять? 
V
    Опции темы
kami
Дата 21.11.2014, 22:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1806
Регистрация: 25.8.2007
Где: Санкт-Петербург

Репутация: нет
Всего: 72



Здравствуйте, уважаемые!
Есть база... пусть будет с адресами, тем более что пока так и есть (улицы и дома) + их координаты.

Нужно: искать в базе по адресам (пример - подсказки Яндекс.Карт и 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% именно "ближайшие к вот такой точке".

Возможно, я неправильно настроил поиск в постгресе или монге. Но, к сожалению, не нашел таких настроек... буду рад, если поделитесь ссылкой.
PM MAIL WWW   Вверх
tzirechnoy
Дата 23.11.2014, 17:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1173
Регистрация: 30.1.2009

Репутация: 0
Всего: 16



Про постгрэсс: так преобразуй его в cp1251 и lower case. Можно -- дажэ не выделяя какого-то поля, прямо в индэксе (только в запросах -- те жэ функцыи, разумеется, должны быть).
PM MAIL   Вверх
kami
Дата 23.11.2014, 19:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1806
Регистрация: 25.8.2007
Где: Санкт-Петербург

Репутация: нет
Всего: 72



Цитата(tzirechnoy @  23.11.2014,  17:05 Найти цитируемый пост)
так преобразуй его в cp1251 и lower case. Можно -- дажэ не выделяя какого-то поля, прямо в индэксе (только в запросах -- те жэ функцыи, разумеется, должны быть). 

Это не избавляет от проблемы 
Цитата(kami @  21.11.2014,  22:59 Найти цитируемый пост)
поиск по "Красно" выдает адреса типа "Краснопутиловская ул." (+ дома на этой улице), "Красная ул." и т.п. А вот запрос "Красноп" уже не выдает вообще ничего. И это "ничего" продолжается до ввода "Краснопутиловск". 


PM MAIL WWW   Вверх
tzirechnoy
Дата 24.11.2014, 14:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1173
Регистрация: 30.1.2009

Репутация: 0
Всего: 16



А можно конкретный пример индэкса и запроса, как это получилось?
PM MAIL   Вверх
tzirechnoy
Дата 24.11.2014, 15:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1173
Регистрация: 30.1.2009

Репутация: 0
Всего: 16



А, кстати понял, да. Надо запросы на начало через :* выделять.

Код
SELECT * FROM ftstest WHERE lower(name) @@ to_tsquery('simple', 'красно:*');

PM MAIL   Вверх
kami
Дата 24.11.2014, 15:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1806
Регистрация: 25.8.2007
Где: Санкт-Петербург

Репутация: нет
Всего: 72



tzirechnoy, да, конечно. Я подозреваю, что просто не умею готовить Postgres.

Тестовая база, примерно 11 тыс. записей.
Исходная таблица (скрипт скопирован из pgAdmin, "лишние" поля удалил):
Код

CREATE TABLE public.streets
(
  id integer NOT NULL DEFAULT nextval('streets_id_seq'::regclass),
  streetfull character varying(150) NOT NULL DEFAULT ''::character varying,
  fullname character varying(250) NOT NULL DEFAULT ''::character varying,
  streetname character varying(120) NOT NULL DEFAULT ''::character varying,
  streetprefix character varying(10) NOT NULL DEFAULT ''::character varying,
  parentcityname character varying(120) NOT NULL DEFAULT ''::character varying,
  geom point,
  CONSTRAINT streets_primary PRIMARY KEY (id)
)
WITH (
  OIDS=FALSE
);

После чего - создан индекс:
Код

CREATE INDEX IX_STREETS ON streets USING gin(to_tsvector('russian', streetfull));

Ну и собственно - запрос:
Код

SELECT * FROM streets
WHERE to_tsvector('russian', streetfull) @@ to_tsquery('russian', 'Краснопу');

Вот по этому запросу ничего не находит.
А по запросу "Краснопутиловск" - находит правильную улицу - "Краснопутиловская". Моя нипанимать, в чем дело...

Добавлено через 1 минуту и 54 секунды
Upd: пока писал, не увидел ответ выше smile
Пробую...

Добавлено через 10 минут и 28 секунд
Цитата(tzirechnoy @  24.11.2014,  15:05 Найти цитируемый пост)
Надо запросы на начало через :* выделять.

Ткните в меня ссылкой на документацию, пожалуйста, где описаны вот такие вот маски для поиска, а то я так долго буду тыкаться, как слепой котенок smile
С "Красноп:*" отрабатывает отлично, а вот с другим запросом "11:* лини:*" - ошибка синтаксиса. Теоретически, он должен находить улицы типа "11-я линия В.О.", "11-я Красноармейская линия" и т.п. Т.е. - в одном запросе - 2 начала слов для поиска.
PM MAIL WWW   Вверх
tzirechnoy
Дата 24.11.2014, 17:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1173
Регистрация: 30.1.2009

Репутация: 0
Всего: 16



Потому, что to_tsquery('russian', '11:* & лини:*')

http://www.postgresql.org/docs/9.3/static/...PARSING-QUERIES

Там ещё ссылка на секцыю 8.11 -- тожэ полезная.
PM MAIL   Вверх
kami
Дата 24.11.2014, 20:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1806
Регистрация: 25.8.2007
Где: Санкт-Петербург

Репутация: нет
Всего: 72



tzirechnoy, спасибо. Относительно понятнее стало, почему так происходит.
Все-таки поведение отличается от того, что мне необходимо.
В частности:
Код
SELECT '10-11 линии В.О.'::tsvector

выдает 
Цитата
"'10-11' 'В.О.' 'линии'"

Т.е.  он считает, что 10-11 - это одна лексема (или как там они называются)...
Даже если сделать так: 
Код
SELECT to_tsvector('simple', '10-11 линии В.О.')

то выдается 
Цитата
"'-11':2 '10':1 'в':4 'линии':3 'о':5"

Как результат - искомые "10-11 линии" оказываются далеко-далеко по ранжированию на запрос типа
Код

SELECT 
  ts_rank_cd(to_tsvector('russian', streetfull), query) AS rank, 
  * 
FROM streets, to_tsquery('russian', '11:* | лини:*') query
WHERE query @@ to_tsvector('russian', streetfull)
ORDER BY rank DESC, Level1Name, Level2Name, Level3Name


А вот MySQL разбивает на лексемы так, как в нашем случае нужно - "10" "11" "В.О." "линии". Вернее, я считаю, что у него не используются лексемы как таковые, а просто разбиение на слова...

Что я продолжаю делать не так?
PM MAIL WWW   Вверх
tzirechnoy
Дата 25.11.2014, 00:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1173
Регистрация: 30.1.2009

Репутация: 0
Всего: 16



Цитата
Что я продолжаю делать не так?


Ну, он, очевидно, не матчит 11.

Если Вы думаете, что - у вас безсмысленнен -- то замените минусы на пробелы.

Заодно, кстати, и lower() сделайте.

Ну и, надо долго медитировать, конечно, по вопросу -- подходит вам встроенный русский словарь или лучшэ без него или лучшэ как-то его изменить.
PM MAIL   Вверх
kami
Дата 27.11.2014, 23:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1806
Регистрация: 25.8.2007
Где: Санкт-Петербург

Репутация: нет
Всего: 72



Прошу прощения за долгое молчание.

Ну, собственно, вопрос можно закрывать.
Путем долгих терзаний и сомнений между Монгой и Постгресом, был выбран Постгрес. Не последнюю роль в этом процессе сыграла монетка, которая легла орлом вверх smile
Бесспорных аргументов "за", по большому счету не было: в обеих системах обеспечить необходимый нам вид поиска можно только с дополнительными извратами. Плюсом Постгреса стала возможность использовать маску ":*", у Монги такого не нашел :(. А жаль, ибо на ней уже крутятся логи многих сервисов и очень хорошо себя чувствуют...

Подводя итог: в таблицах для обеспечения FTS будут созданы "нормализованные" поля, содержащие вместо всех знаков препинания - пробелы, все буквы - в одном регистре (без разницы - нижний или верхний, емнип, выбрали нижний). Эти поля будут заполняться программно, а не средствами СУБД. Дополнительно - рядом с ними будут поля типа ::tsvector (шаблон simple) (правда, моя нипанимать - зачем это надо, неужто полнотекстовый индекс, созданный по "нормализованному полю" - на самом деле не индекс?)

Полагаю, все следующие вопросы пойдут уже в профильный раздел.

Еще раз спасибо.

Это сообщение отредактировал(а) kami - 27.11.2014, 23:13
PM MAIL WWW   Вверх
tzirechnoy
Дата 27.11.2014, 23:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1173
Регистрация: 30.1.2009

Репутация: 0
Всего: 16



Цитата
 для обеспечения FTS будут созданы "нормализованные" поля,


А зачем? Всё равно ведь большынство БД -- IO-bound, смысл увеличивать количество данных на диске, экономя на преобразовании "на лету"?

Добавлено через 48 секунд
Цитата
правда, моя нипанимать - зачем это надо, неужто


Моя тожэ.

Добавлено через 1 минуту и 19 секунд
В смысле -- я совершэнно непонимаю, зачем тебе это понадобилось и почему ты считаешь, что это поле что-нибудь изменит.
PM MAIL   Вверх
tzirechnoy
Дата 28.11.2014, 00:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1173
Регистрация: 30.1.2009

Репутация: 0
Всего: 16



А, я кажэтся понял. Вы не увидел postgres function index http://www.postgresql.org/docs/9.3/static/...pressional.html.

Так вот, они здесь есть. И можно писать что-то вроде 
Код
CREATE INDEX fts_ndx ON table USING gin (to_tsvector('simple', translate(lower(name), '#$@!,.=-:;`"', '            ')));


При поиске, конечно, надо будет всегда указывать ровно те жэ функцыи, т.е.:
Код

SELECT ... FROM table WHERE to_tsvector('simple', translate(lower(name), '#$@!,.=-:;`"', '            ')) @@ 'query_expression';


Это сообщение отредактировал(а) tzirechnoy - 28.11.2014, 00:58
PM MAIL   Вверх
kami
Дата 29.11.2014, 15:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1806
Регистрация: 25.8.2007
Где: Санкт-Петербург

Репутация: нет
Всего: 72



Цитата(tzirechnoy @  28.11.2014,  00:57 Найти цитируемый пост)
Так вот, они здесь есть. И можно писать что-то вроде 

Кошмар какой smile
Примерно такие же непонятки я испытывал, когда узнал, что у MySQL на каждый чих задается своя кодировка.
PM MAIL WWW   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Общие вопросы по базам данных"
LSD
Zloxa

Данный форум предназначен для обсуждения вопросов о базах данных не попадающих под тематику других форумов:

  • вопросам по СУБД для которых нет отдельных подфорумов
  • вопросам которые затрагивают несколько разных СУБД (например проблема выбора)
  • инструменты для работы с СУБД
  • вопросы проектирования БД
  • теоретически вопросы о СУБД

Данный форум не предназначен для:

  • вопросов о поиске разлиных БД (если не понимаете чем БД отличается от СУБД то: а) вам не сюда; б) Google в помощь)
  • обсуждения проблем с доступом к СУБД из различных ЯП (для этого есть соответсвующие форумы по каждому ЯП)
  • обсуждения проблем с написание SQL запросов, для этого есть форум Составление SQL-запросов
  • просьб о написании курсовой, реферата и т.п., для этого есть Центр помощи или фриланс биржа
  • объявлений о найме специалистов, для этого есть раздел Объявления о найме специалистов

Если вы не соблюдаете эти правила, не удивляйтесь потом не найдя свою тему/сообщение. ;)


Полезные советы:

При написании сообщения постарайтесь дать теме максимально понятное название. В теме максимально подробно опишите проблему. Если применимо укажите: название базы данных и версии (MySQL 4.1, MS SQL Server 2000 и т.п.); используемых язык программирования; способа доступа (ADO, BDE и т.д.); сообщения об ошибках.

Для вставки кода используйте теги [code=sql] [/code].

Литературу по базам данных можно поискать здесь.

Действия модераторов можно обсудить здесь.


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, LSD, Zloxa.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | СУБД, общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0554 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.