Open Scondo opened 11 years ago
Частично решено, частично - нет. Возможно дальнейшее решение требует наполнение базы стритмэнглера. Пример для сверки - Новый Берингов проезд, г. Москва
Да блин же, не нужен тебе streetmangler. Для сопоставления нужно преобразовать название улицы из обеих баз одинаковым образом:
всё, названия можно сравнивать.
По желанию можно добавить всякую мелочь типа удаления окончания числительных ("1-я", "1-ая" -> "1"), пробелов после одной буквы с точкой ("Л. Толстого" -> "Л.Толстого", это только до сортировки слов) и всего прочего, но это даст копейки.
А в списке, к слову, стоит их писать в виде "статусная часть в конце" - так удобнее искать нужное в таблице.
Насчет сортировки по алфавиту - интересная мысль, но для этого опять-таки придется вытягивать все в память, чего я мало того что не хочу, так еще и переписывать значительную часть придется. И еще придется бороться с задвоением статусных частей. Как запасной вариант возможно, но пока я ищу более изящное решение.
Кроме того, нарвался я на проезд Берингов Н. и как его с Новым Беринговым проездом сопоставлять - это и сокращения раскрывать (надо, правда, посмотреть что там в двух разных столбцах, но с этой кашей все равно лучше подумать..)
Насчет сортировки по алфавиту - интересная мысль, но для этого опять-таки придется вытягивать все в память
Что? Ничего не надо менять, просто сравнивай названия по-человечески и выбрось streetmangler который тут совершенно не нужен.
И еще придется бороться с задвоением статусных частей.
Что?
Кроме того, нарвался я на проезд Берингов Н. и как его с Новым Беринговым проездом сопоставлять - это и сокращения раскрывать (надо, правда, посмотреть что там в двух разных столбцах, но с этой кашей все равно лучше подумать..)
Такое - только руками.
Сортировать слова прямо внутри SQL - запроса? У меня база родная из osm2pgsql, в ней сначала по результату стритманглера ищется с условием
WHERE lower(name) = lower(%s) AND ST_Within(way,%s)
Если не найдено выгребается с условием
WHERE lower(name) LIKE lower(%s) AND ST_Within(way,%s)
Из которого потом ищется совпадение с именем без статусной/со статусной в начале/со статусной в конце
Про задвоение статусных: информация хранится в виде отдельно названия, отдельно статуса. Название как правило без статусной части. Но может быть и со статусной. То есть улица Амундсена выглядит как "Амундсена" "ул", а площадь Гагарина может раскладываться также, а может "пл. Гагарина" "пл", что приводит к "площадь пл. Гагарина" я так понимаю и сейчас :( Так что буду в любом случае думать что с этим мраком делать.
У меня база родная из osm2pgsql, в ней сначала по результату стритманглера ищется с условием
А, так. Понял. Тогда всё плохо, ибо это неправильный подход. В идеале нужен индекс по normalize_name(name) и искать по нему на = normalize_name(%s), где normalize_name - некая функция которая делает то что я говорил. Не знаю можно ли и насколько сложно написать её на sql или или другом языке.
WHERE lower(name) LIKE lower(%s) AND ST_Within(way,%s)
я всё-таки не понял зачем нужен LIKE. Он же даст только ложные срабатывания на названия с добавлениями в начале/в конце, т.е. Ленинская улица совпадёт со всеми 123-ми Новыми Нижними Ленинскими, при этом нормальных случаев не зацепит (улица Толстого vs. улица Л.Толстого, например). Он ещё и full-scan. Кстати, индекс по name-то у тебя, надеюсь, на lower(name)?
Про задвоение статусных: информация хранится в виде отдельно названия, отдельно статуса. Название как правило без статусной части. Но может быть и со статусной.
Это трындец. Но статусные части вырезать легко и это можно сделать на SQL. Вот тут можно сделать два варианта - с вырезанием статусной части и без (потому что в базе есть названия с несколькими ст. частями типа "улица Ленинская набережная")
LIKE + фильтр на клиентской стороне до точного соответствия оказался быстрее трех запросов на точное соответствие (очевидно по причине меньшего числа геометрических сравнений). В общем решаем задачу по частям. Этот тикет на сокращения, закрыли оффтоп.
LIKE + фильтр на клиентской стороне до точного соответствия оказался быстрее трех запросов на точное соответствие
Смотри explain. Что-то мне кажется что индексы по name не работают.
LIKE легко ускоряется использованием gin-индексами
Ряд улиц с номерами не находятся из-за того что в ОСМ пишутся <номер> <статус> <остальное название> Также не находятся улицы с сокращениями. Обе эти проблемы можно решить использованием streetmangler при "поиске кандидатов"