Как устроены адресные подсказки «Дадаты»



    «Дадата» с 2014 года пилит «Подсказки». Они помогают быстро и без ошибок вводить контактные данные: адреса, реквизиты банков и компаний, емейлы — вот это все.


    Штука устроена затейливо, и мы решили о ней рассказать. Возьмем подсказки по адресам, потому что они самые сложные.


    Справочники и индексация


    «Подсказки» знают, что подсказывать, потому что у них есть гигантские справочники. Хоть статья эта о подсказках по адресам, для пользы дела перечислю и другие справочники «Дадаты».


    Для чего подсказки Какие справочники Где взять справочники
    Адреса ФИАС Скачать с официального сайта
    Юрлица ЕГРЮЛ и ЕГРИП Купить у ФНС годовой доступ — 150 000 ₽ за справочник
    Банки Справочник по кредитным организациям ЦБ РФ Скачать с официального сайта
    ФИО Фамилии, имена, отчества Собрать самому или поискать готовые
    Емейлы
    • Домены первого уровня;
    • топ 40 000 доменов второго уровня Рунета;
    • бесплатные провайдеры (yandex.ru, mail.ru);
    • популярные названия ящиков


    Искать что-то в неподготовленном справочнике — дело долгое и неблагодарное. Поэтому мы берем чудесную библиотеку Lucene и превращаем исходные данные в поисковый индекс.


    Поисковый индекс — такой формат, при котором находить информацию можно оооочень быстро.


    Физически индекс представляет из себя набор двух типов файлов:


    • файлы с собственно индексом, по ним «Подсказки» ищут. Индексную часть мы держим в оперативной памяти, чтобы сервис был бодрым и подтянутым;
    • файлы с данными. Из них «Подсказки» возвращают ответ.

    Индекс и данные по адресам в сумме занимают 20 гигабайт. По компаниям примерно столько же, а остальные весят меньше.


    Из официальных справочников для экономии убираем данные, по которым не ищем и которые не возвращаем. Также вычищаем дубли и очевидные ошибки. Например, в индексе по адресам нет:


    • литер домов. В ФИАС колоссальное количество литер, которых на самом деле не существует;
    • заведомо невозможных объектов вида «дом 21/2, стр 21/2».

    Поиск адекватных подсказок


    «Подсказки» работают довольно заковыристо. Для простоты разобью процесс на этапы и расскажу о каждом подробнее. Если останутся вопросы, спрашивайте в комментариях.


    1. Поехали: человек вводит символы в поле «Подсказок».




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

    2. Плагин «Подсказок» собирает запрос. Между человеком и сервером трудится диспетчер — jQuery-плагин «Подсказок» (исходный код на GitHub).


    Плагин принимает данные для поиска, упаковывает в запрос и передает на сервер.


    От себя плагин добавляет, сколько адресов вернуть. Число задают как параметр при интеграции «Подсказок». Если количество не указали, «Подсказки» возвращают 10 результатов. Больше 20 просить бесполезно — вернутся только 20 вариантов.


    Также плагин передает параметры фильтрации, их тоже задают при интеграции «Подсказок». Вот какие фильтры существуют:


    • по родителю (искать только по Московскому шоссе в Самаре);
    • по уровню ФИАС (искать только населенные пункты);
    • по типу объекта (полезно, потому что в ФИАС на уровне городов лежат посторонние объекты вроде сельсоветов. Если не указать тип «город», «Подсказки» вернут и сельсоветы).

    А еще есть такая штука как geoboost. Похожа на ограничение по родителю, но влияет только на ранжирование адресов. Хотите, чтобы омские улицы стояли выше московских — пожалуйста.




    «Яндекс.Деньги» по умолчанию предлагают улицы Москвы. Ограничение на город настраивают через параметры фильтрации «Подсказок»

    По умолчанию в плагине включена геолокация: он передает на сервер местоположение пользователя. Это тоже параметр поиска.


    При интеграции можно регулировать задержку запросов к серверу. Например, поставили задержку 100 миллисекунд. Если некий виртуоз за 100 миллисекунд вбил четыре символа, на сервер уйдет один запрос с четырьмя новыми символами. А не четыре запроса по одному.


    Плагин работает в IE начиная с версии 10 и всех нормальных браузерах. Еще ему нужен jQuery 1.10+.


    3. Проверяем кэш. Когда запрос приходит на сервер, «Подсказки» первым делом смотрят в кэш. Ищут там совпадение по всем параметрам запроса до единого.


    Кэширование спасает от коротких запросов вроде «М», «Мо», «С». Таких однотипных комбинаций приходит колоссальное количество. Поскольку каждая буква — это отдельный запрос, кэширование защищает сервер от миллионов обращений к поисковому индексу.


    Кэш целиком помещается в оперативной памяти, в нем лежит 100 000 результатов.


    4. Ищем подходящие подсказки в индексе. Если в кэше ничего подходящего нет, «Подсказки» направляются в поисковый индекс.


    «Подсказки» ищут адреса́ по:


    • любой части;
    • почтовому индексу;
    • устаревшим названиям;
    • синонимам и сокращениям. Для них мы составили словарь: «Мск», «Спб», «Ебург», «Б.» — «большая» и т. д.

    Алгоритм подразумевает, что неполное или ошибочное в запросе только последнее слово. Если человек написал «Москва Турч», «Подсказки» ищут «Москва Турч*».




    Запросы вроде «москв турч» не пройдут. Проблем это не создает, потому что люди набирают адреса́ последовательно, и «Подсказки» последовательно предлагают правильное написание каждой части а́дреса

    Если в плагине отключили геолокацию, по запросам в 1-2 символа, «Подсказки» ищут только регионы, муниципальные районы и города. Дома́ сервис ищет со второго слова в запросе.


    Каждому результату «Подсказки» назначают вес. Вес нужен, потому что алгоритм порой находит тысячи вариантов, особенно для коротких запросов. А вернуть можно максимум 20 штук. Поэтому «Подсказки» сортируют результаты по весу и возвращают топовые.


    Алгоритм ранжирования результатов — ноу-хау «Дадаты». Это такая серьезная штука, что описывать ее подробно я не могу: проклянут разработчики.


    5. Сортируем результаты. Если у результатов поиска одинаковый вес, «Подсказки» их сортируют. Алгоритм сортировки тоже самописный, поэтому снова сохраняю таинственность.


    6. Готовим ответ. Адреса, которые возвращают «Подсказки», по формату немного отличаются от ФИАС:


    • города-регионы вроде Москвы возвращаются в полях и region, и city. В ФИАС они только в region. О доработке просили интернет-магазины: курьерские службы требуют от них, чтобы город стоял непременно в поле «город» (каковы!);
    • адрес одной строкой записан по правилам Почты России. Поэтому центр региона отдается без названия региона, а центр района — ну вы поняли. Например, Новосибирск вернется без Новосибирской области. Полный адрес тоже есть, он возвращается в поле unrestrictabled_value;
    • тип «улица», «переулок», «шоссе» подставляются перед или после объекта в зависимости от того, как лучше звучит. Благозвучность оцениваем по окончаниям: «Авиационный переулок», но «переулок Васнецова»;
    • к садовым товариществам и всему остальному с 65-го уровня ФИАС добавляется название родительского населенного пункта. Например, «снт Гигант (п. Новый)». По ФИАС садовые товарищества входят в населенные пункты, но людям такая иерархия непривычна. Поэтому последние просто выводятся в скобках как ориентир на местности.

    7. Кэшируем. Прежде чем вернуть результат, «Подсказки» кэшируют запрос со всеми параметрами и с ответом.


    Кэш ограничен 100 000 записей по алгоритму LRU, поэтому сервис выкидывает оттуда редкие запросы. Популярные же вроде «Мо» висят в кэше вечно.


    8. Плагин рисует подсказки. Он принимает ответ от сервера, показывает адреса́ на экране и подсвечивает совпадения. Если во время ввода нажать Enter, плагин сравнит текст с найденными подсказками и подставит в поле самую подходящую.


    Вот так все и работает. Если возьметесь за свои подсказки, статья хоть немного поможет. А лучше приходите к нам работать, будем вместе придумывать крутые штуки. Прямо сейчас ищем джависта на «Подсказки» и еще 7 специалистов.

    HFLabs 87,30
    Качество и интеграция клиентских данных
    Поделиться публикацией
    Комментарии 10
      +1
      выбрать популярные домены второго уровня из списка Alexa

      — как то не очевидно, что от этого есть польза. Думаю большинство пользователей применяет ящики небольшого количества бесплатных почтовых систем (типа mail.ru или gmail.com) и ящики на доменах которых нет в топе Alexa (знаю много случае когда у пользователя есть домен на котором висят ящики, но на этом домене не висит сайта или каких то других сервисов). Я бы использовал другую логику: известные почтовики + корпоративные домены
        0

        Безусловно, больше всего ящиков у бесплатных провайдеров, поэтому Дадата предлагает их в первую очередь:
        image

        0
        а почему прямо lucene, а не elasticsearch, например? :)

        его не было, когда начинали, а теперь неудобно переходить, или какие-то более другие причины?
          0
          Я не автор, поэтому могу лишь предположить, что так объем данных относительно невелик:
          Индекс и данные по адресам в сумме занимают 20 гигабайт. По компаниям примерно столько же, а остальные весят меньше.

          а Elasticsearch это продукт который нуждается в некотором администрировании, в отличии от Lucene, который используется как встроенное решение без администрирования, то выбрали более компактное и простое решение.
            +1

            Люсин легче и гибче. Эластик хорош, когда нужно готовое решение для распределённых серверов с API. А нам скорее нужен мощный движок, который можно тюнить под специализированные задачи. Поэтому Люсин.

            0
            заведомо невозможных объектов вида «дом 21/2, стр 21/2».

            Не хотите ли вы сказать, что в ФИАС такие есть?

              0

              Именно.

                0

                Хм. Окей, тогда второй вопрос — а как узнать, что адрес невозможен? Ну допустим, стр 21/2 не бывает, потому что это не дом по двум улицам. И это вся магия? Потому что по номеру строения/корпуса я бы отбирать не стал, ибо есть такие явления, как бывшие заводы, а ныне торговые центры, и где номер дома один а строения десятками. Савеловский рынок в Москве, или скажем ул. Орджоникидзе 11. Так что строением номер 50 нас не удивить.

                  0

                  Никак не узнать :–)

                  0
                  Это без улицы, сразу в населённом пункте? А то в Нижнем есть «улица Дьяконова, 2/3», но после дроби не корпус и не номер по другой улице.

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

              Самое читаемое