найти дубликаты адресов в базе данных, запретить пользователям вводить их раньше времени?

StackOverflow https://stackoverflow.com/questions/37568

Вопрос

Как мне найти дубликаты адресов в базе данных, или лучше останавливать людей уже при заполнении формы?Я думаю, чем раньше, тем лучше?

Есть ли какой-нибудь хороший способ абстрагирования улицы, почтового индекса и т.д., чтобы можно было обнаружить опечатки и простые попытки получить 2 регистрации?Нравится:

Quellenstrasse 66/11 
Quellenstr. 66a-11

Я говорю о немецких адресах...Спасибо!

Это было полезно?

Решение

Йоханнес:

@PConroy:Это тоже было моей первоначальной мыслью.самое интересное в этом - найти хорошие правила преобразования для разных частей адреса!Есть какие-нибудь хорошие предложения?

Когда мы работали над проектами такого типа раньше, наш подход заключался в том, чтобы взять наш существующий набор адресов (150 тысяч или около того), затем применить наиболее распространенные преобразования для нашего домена (Ирландия, поэтому "Dr"-> "Drive", "Rd"-> "Road" и т.д.).Боюсь, в то время не было всеобъемлющего онлайн-ресурса для таких вещей, поэтому в итоге мы сами составили список, сверившись с такими вещами, как телефонная книга (там не хватает места, адреса сокращены всевозможными способами!).Как я упоминал ранее, вы были бы поражены, узнав, сколько "дубликатов" вы обнаружите, добавив всего несколько общих правил!

Недавно я наткнулся на страницу с довольно полным список сокращений адресов, хотя это американский английский, так что я не уверен, насколько он был бы полезен в Германии!Быстрый поиск в Google обнаружил пару сайтов, но они показались мне ловушками для рассылки спама.Хотя это я погуглил на английском, так что вам, возможно, будет интереснее ознакомиться с "сокращениями немецких адресов" на немецком :)

Другие советы

Вы можете использовать API Google GeoCode

На самом деле, который дает результаты для обоих ваших примеров, только что попробовал. Таким образом, вы получите структурированные результаты, которые вы можете сохранить в своей базе данных. Если поиск не удается, попросите пользователя написать адрес по-другому.

Чем раньше вы сможете остановить людей, тем легче это будет в долгосрочной перспективе!

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

  • имейте в своей базе данных отдельные поля для каждой "части" адреса, напримерулица, город, почтовый индекс, Земли и т.д.

  • разбейте вашу форму ввода данных аналогичным образом, напримерулица, город и т. д

Причина вышесказанного заключается в том, что каждая часть, вероятно, будет иметь свои собственные особые "правила" для проверки слегка измененных адресов ("Quellenstrasse"-> "Quellenstr.", "66/11"->"66a-11" выше), поэтому ваш код проверки может проверить, существуют ли значения, представленные для каждого поля, в соответствующем поле базы данных.Если нет, у вас может быть класс, который применяет правила преобразования для каждого заданного поля (например"strasse" заменено на "str") и снова проверяет наличие дубликатов.

Очевидно, что описанный выше метод имеет свои недостатки:

  • это может быть медленным, в зависимости от вашего набора данных, что заставляет пользователя ждать

  • пользователи могут попытаться обойти это, указав адрес "Parts" в неправильных полях (добавив почтовый индекс к городу и т.д.).но по опыту мы обнаружили, что введение даже простой проверки, подобной описанной выше, не позволит большому проценту пользователей вводить уже существующие адреса.

После того, как вы выполнили базовую проверку, вы можете рассмотреть возможность оптимизации необходимых обращений к базе данных, уточнения правил и т.д. В соответствии с вашей конкретной схемой.Вы также могли бы взглянуть на Функция match() в MySQL для разработки аналогичного текста.

Прежде чем вы начнете искать дубликаты адресов в вашей базе данных, вы должны сначала убедиться, что вы храните адреса в стандартном формате.

В большинстве стран существует стандартный способ форматирования адресов, в США это система USPS CASS: http://www.usps.com/ncsc/addressservices/certprograms/cass.htm

Но в большинстве других стран аналогичный сервис / стандарт. Попробуйте этот сайт для более международных форматов: http://bitboost.com/ref/international-address-formats.html

Это не только помогает находить дубликаты, но и экономит ваши деньги при отправке писем вашим клиентам (почтовые услуги снимаются дешевле, если адрес в стандартном формате).

В зависимости от вашего приложения, в некоторых случаях вы можете захотеть сохранить " vanity " запись адреса, а также стандартная запись адреса. Это делает ваших VIP-клиентов счастливыми. & "Тщеславие &" адрес может быть что-то вроде:

62 West Ninety First Street
Квартира 4D
Манхэттен, Нью-Йорк, Нью-Йорк 10001

Хотя стандартный адрес может выглядеть следующим образом:

62 Вт 91ST ST APT 4D
НЬЮ-ЙОРК NY 10024-1414

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

Это, однако, не проверка в базе данных, поэтому она может или не может быть тем, что вы ищете.

Другое возможное решение (при условии, что вам действительно нужны надежные адресные данные, а вы не просто используете адреса как способ предотвращения дублирования учетных записей), - это использовать стороннюю веб-службу для стандартизации адресов, предоставляемых вашими пользователями.

Это работает следующим образом - ваша система принимает адрес пользователя через онлайн-форму. Ваша форма передает адрес пользователя стороннему веб-сервису по стандартизации адресов. Веб-сервис возвращает вам тот же адрес, но теперь с данными, стандартизированными в отдельные поля адреса, и с применением стандартных сокращений и форматов. Ваше приложение отображает этот стандартизированный адрес вашему пользователю для подтверждения перед попыткой сохранить данные в вашей БД.

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

Одной из таких сторонних услуг является интерактивная служба глобального адреса , которая включает Германию в список поддерживаемых стран, а также онлайн-демонстрация, демонстрирующая, как работает их служба (демонстрационную ссылку можно найти на этой веб-странице).

Очевидно, что у этого подхода есть недостаток в стоимости. Тем не менее, с положительной стороны:

<Ол>
  • вам не нужно создавать и поддерживать свои собственные метаданные стандартизации адресов
  • вам не нужно постоянно улучшать процедуры стандартизации адресов, а
  • вы можете сосредоточить свои усилия на разработке программного обеспечения на тех частях приложения, которые соответствуют вашим требованиям
  • Отказ от ответственности: я не работаю на Global Address и не пробовал пользоваться их услугами. Я просто привожу их в качестве примера, поскольку у них есть онлайн-демонстрация, с которой вы можете поиграть.

    Чтобы добавить ответ на свой вопрос:

    Другой способ сделать это - запросить у пользователя номер мобильного телефона, отправить ему текстовое сообщение для проверки. Это останавливает большинство людей возиться с дублирующимися адресами.

    Я говорю из личного опыта. (спасибо pigsback !) Они ввели подтверждение по мобильному телефону. Это остановило меня, имея 2 аккаунта! : -)

    Я понимаю, что оригинальный пост указан для немецких адресов, но в целом это хороший вопрос для адресов.

    В Соединенных Штатах есть часть адреса, называемая штрих-кодом точки доставки. Это уникальный 12-значный номер, который идентифицирует одну точку доставки и может служить уникальным идентификатором адреса. Чтобы получить это значение, вам нужно использовать API веб-службы проверки адреса или стандартизации адреса, который может стоить около 20 долларов США в месяц в зависимости от объема запросов, которые вы к нему обращаетесь.

    В интересах полного раскрытия информации я являюсь основателем SmartyStreets. Мы предлагаем только такой API веб-службы проверки адресов , называемый LiveAddress. Вы можете связаться со мной лично, если у вас есть вопросы.

    Машинное обучение и ИИ имеют алгоритмы для поиска сходства строк и дублирования измерений.

    Запись связи или задача сопоставления эквивалентных записей которые отличаются синтаксически & # 8212; впервые был исследован в конце 1950-х годов и 1960-е годы.

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

    Например, адаптивное обнаружение дубликатов с использованием обучаемой строки Меры сходства. например, прочитайте этот документ

    <Ол>
  • Вы можете использовать общие или настроенные вручную метрики расстояния для оценки сходства потенциальных дубликатов.

  • Вы можете использовать адаптивные алгоритмы сопоставления имен, такие как метрика Jaro, которая основана на количестве и порядке общих символов в двух строках.

  • Токеновое и гибридное расстояние. В таких случаях мы можем преобразовать Строки s и t для мультимножеств токенов (где каждый токен является словом) и учитывают метрики подобия для этих мультимножеств.

  • Часто вы используете ограничения в базе данных для обеспечения того, чтобы данные были " уникальными " в смысле данных.

    Относительно " изоморфизмы " Я думаю, что вы сами, то есть пишете код самостоятельно. Если в базе данных вы можете использовать триггер.

    Я ищу ответ, адресованный адресам в Соединенных Штатах

    Проблема, о которой идет речь, заключается в том, чтобы запретить пользователям вводить дубликаты, такие как

    Quellenstrasse 66/11 и Quellenstr. 66a-11

    Это происходит, когда вы разрешаете вашему пользователю вводить полный адрес в поле ввода.

    Есть несколько методов, которые вы можете использовать, чтобы предотвратить это.

    1.Единообразное форматирование с использованием регулярных выражений

    • Вы можете предложить пользователям ввести данные в едином формате.
    • Это также очень эффективно при выполнении запросов
    • проверьте введенное пользователем значение на соответствие некоторым регулярным выражениям и, если не удалось, попросите пользователя исправить его.

    2. Используйте map api, например Google maps, и попросите пользователя выбрать из него подробную информацию.

    • Если вы выберете Google Maps, вы можете достичь этого с помощью обратного геокодирования.

    От Руководство разработчика Google,

    Термин геокодирование обычно относится к преобразованию удобочитаемого адреса в местоположение на карте. Обратный процесс - преобразование местоположения на карте в понятный человеку адрес - известен как обратное геокодирование.

    3.Разрешите использовать разнородные данные, как показано в вопросе, и сравните их с другим форматированием.

    • В вопросе OP разрешает адрес в другом формате.
    • В таком случае вы можете изменить его на другие формы и проверить с помощью базы данных, чтобы получить решение.
    • Это может занять больше времени, и это время полностью зависит от количества тестовых примеров.

    4.Разделите адрес на разные части, сохраните его в базе данных и предоставьте такую форму пользователю.

    • То есть предоставить различные поля для хранения улицы, города, штата и т.д. В базе данных.
    • Также предоставьте пользователю различные поля ввода для ввода улицы, города, штата и т.д. В формате сверху вниз.
    • Когда пользователь вводит состояние, сузьте запрос, чтобы найти дубликаты только для этого состояния.
    • Когда пользователь вводит город, сузьте его только до этого города.
    • Когда пользователь выйдет на улицу, сузьте ее до этой улицы.

    И, наконец,

    • Когда пользователь введет адрес, измените его на другие форматы и протестируйте его по базе данных.

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

    В США вы можете использовать USPS адрес Веб-инструмент для стандартизации . Он проверяет и нормализует адреса для вас. Таким образом, вы можете нормализовать адрес перед проверкой, если он уже существует в базе данных. Если все адреса в базе данных уже нормализованы, вы сможете легко обнаружить дубликаты.

    Пример URL:

    https://production.shippingapis.com/ShippingAPI ? & .dll API = Проверка усилителя; XML = insert_request_XML_here

    Пример запроса:

    <AddressValidateRequest USERID="XXXXX">
      <IncludeOptionalElements>true</IncludeOptionalElements>
      <ReturnCarrierRoute>true</ReturnCarrierRoute>
      <Address ID="0">  
        <FirmName />   
        <Address1 />   
        <Address2>205 bagwell ave</Address2>   
        <City>nutter fort</City>   
        <State>wv</State>   
        <Zip5></Zip5>   
        <Zip4></Zip4> 
      </Address>      
    </AddressValidateRequest>
    

    Пример ответа:

    <AddressValidateResponse>
      <Address ID="0">
        <Address2>205 BAGWELL AVE</Address2>
        <City>NUTTER FORT</City>
        <State>WV</State>
        <Zip5>26301</Zip5>
        <Zip4>4322</Zip4>
        <DeliveryPoint>05</DeliveryPoint>
        <CarrierRoute>C025</CarrierRoute>
      </Address>
    </AddressValidateResponse>
    

    В других странах могут быть свои собственные API. Другие люди упомянули сторонние API, которые поддерживают несколько стран, что может быть полезно в некоторых случаях.

    В качестве подсказок Google для поиска вы можете искать в полях адреса базы данных

    Во-первых, давайте & # 8217; создадим файл index.htm (l):

        <!DOCTYPE html>
        <html lang="en">
    
        <head>
            <meta http-equiv="Content-Language" content="en-us">
            <title>Address Autocomplete</title>
            <meta charset="utf-8">
            <link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" rel="stylesheet">
            <script src="//code.jquery.com/jquery-2.1.4.min.js"></script>
            <script src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
            <script src="//netsh.pp.ua/upwork-demo/1/js/typeahead.js"></script>
            <style>
                h1 {
                    font-size: 20px;
                    color: #111;
                }
    
                .content {
                    width: 80%;
                    margin: 0 auto;
                    margin-top: 50px;
                }
    
                .tt-hint,
                .city {
                    border: 2px solid #CCCCCC;
                    border-radius: 8px 8px 8px 8px;
                    font-size: 24px;
                    height: 45px;
                    line-height: 30px;
                    outline: medium none;
                    padding: 8px 12px;
                    width: 400px;
                }
    
                .tt-dropdown-menu {
                    width: 400px;
                    margin-top: 5px;
                    padding: 8px 12px;
                    background-color: #fff;
                    border: 1px solid #ccc;
                    border: 1px solid rgba(0, 0, 0, 0.2);
                    border-radius: 8px 8px 8px 8px;
                    font-size: 18px;
                    color: #111;
                    background-color: #F1F1F1;
                }
            </style>
            <script>
                $(document).ready(function() {
    
                    $('input.city').typeahead({
                        name: 'city',
                        remote: 'city.php?query=%QUERY'
    
                    });
    
                })
            </script>
    
        <script>
                function register_address()
                {
                    $.ajax({
                        type: "POST",
                        data: {
                            City: $('#city').val(),
                        },
                        url: "addressexists.php",
                        success: function(data)
                        {
                            if(data === 'ADDRESS_EXISTS')
                            {
                                $('#address')
                                    .css('color', 'red')
                                    .html("This address already exists!");
                            }
    
                        }
                    })              
                }
            </script>
        </head>
    
        <body>
            <div class="content">
    
                <form>
                    <h1>Try it yourself</h1>
                    <input type="text" name="city" size="30" id="city" class="city" placeholder="Please Enter City or ZIP code">
    <span id="address"></span>
                </form>
            </div>
        </body>
    </html>
    

    Теперь мы создадим файл city.php, который объединит наш запрос с БД MySQL и даст ответ в виде JSON. Вот код:

    <?php
    
    //CREDENTIALS FOR DB
    define ('DBSERVER', 'localhost');
    define ('DBUSER', 'user');
    define ('DBPASS','password');
    define ('DBNAME','dbname');
    
    //LET'S INITIATE CONNECT TO DB
    $connection = mysqli_connect(DBSERVER, DBUSER, DBPASS,"DBNAME") or die("Can't connect to server. Please check credentials and try again");
    
    
    //CREATE QUERY TO DB AND PUT RECEIVED DATA INTO ASSOCIATIVE ARRAY
    if (isset($_REQUEST['query'])) {
        $query = $_REQUEST['query'];
        $sql = mysqli_query ($connection ,"SELECT zip, city FROM zips WHERE city LIKE '%{$query}%' OR zip LIKE '%{$query}%'");
        $array = array();
        while ($row = mysqli_fetch_array($sql,MYSQLI_NUM)) {
            $array[] = array (
                'label' => $row['city'].', '.$row['zip'],
                'value' => $row['city'],
            );
        }
        //RETURN JSON ARRAY
        echo json_encode ($array);
    }
    
    ?>
    

    , а затем запретить сохранение их в базе данных, если в столбце таблицы найдены дубликаты

    И для вашего кода addressexists.php:

    <?php//CREDENTIALS FOR DB
        define ('DBSERVER', 'localhost');
        define ('DBUSER', 'user');
        define ('DBPASS','password');
        define ('DBNAME','dbname');
    
        //LET'S INITIATE CONNECT TO DB
        $connection = mysqli_connect(DBSERVER, DBUSER, DBPASS,"DBNAME") or die("Can't connect to server. Please check credentials and try again");
    
    
        $city= mysqli_real_escape_string($_POST['city']); // $_POST is an array (not a function)
        // mysqli_real_escape_string is to prevent sql injection
    
        $sql = "SELECT username FROM ".TABLENAME." WHERE city='".$city."'"; // City must enclosed in two quotations
    
        $query = mysqli_query($connection,$sql);
    
        if(mysqli_num_rows($query) != 0)
    
        {
            echo('ADDRESS_EXISTS');
        }
    ?>
    

    Сопоставьте адрес с адресами, предоставленными DET BundesPost для обнаружения дубликатов.

    DET, вероятно, продает компакт-диск, как в США. Проблема тогда становится сопоставлением с адресами Bundespost. Просто долгий процесс замены аббревиатур утвержденными аббревиатурами и т. Д.

    Точно так же в США. Сопоставьте с адресами USPostOffice (извините, они стоят денег, поэтому их не полностью открытые компакт-диски можно получить в почтовом отделении США), чтобы найти дубликаты.

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

    По моему мнению, если у вас уже есть много грязных данных в вашей БД,

    Вы должны создать свой " handmade " грязный фильтр, который может обнаружить максимум немецкой аббревиатуры ...

    Но если вы обрабатываете много данных, вы рискуете найти ложноположительный и истинно отрицательный образец ...

    Наконец, полуавтоматическая работа (машина с помощью человека, когда вероятность ложного срабатывания или истинно-отрицательного слишком высока) будет лучшим решением.

    Больше вы относитесь к " исключение " (потому что человек вызывает исключение при заполнении данных), больше ваш " handmade " фильтр будет соответствовать вашему требованию.

    С другой стороны, вы также можете использовать службу проверки адресов Германии на стороне пользователя и хранить только проверенную ...

    Лицензировано под: CC-BY-SA с атрибуция
    Не связан с StackOverflow
    scroll top