¿Encontrar direcciones duplicadas en la base de datos y evitar que los usuarios las ingresen temprano?

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

Pregunta

¿Cómo encuentro direcciones duplicadas en una base de datos, o mejor, detengo a las personas cuando completan el formulario?¿Supongo que cuanto antes mejor?

¿Existe alguna buena forma de abstraer la calle, el código postal, etc. para poder detectar errores tipográficos e intentos simples de obtener 2 registros?como:

Quellenstrasse 66/11 
Quellenstr. 66a-11

Estoy hablando de direcciones alemanas...¡Gracias!

¿Fue útil?

Solución

Juan:

@PConroy:Este también fue mi pensamiento inicial.¡Lo interesante de esto es encontrar buenas reglas de transformación para las diferentes partes de la dirección!¿Alguna buena sugerencia?

Cuando trabajábamos en este tipo de proyecto anteriormente, nuestro enfoque era tomar nuestro corpus de direcciones existente (150k aproximadamente) y luego aplicar las transformaciones más comunes para nuestro dominio (Irlanda, entonces "Dr"->"Drive", " Rd"->"Carretera", etc.).Me temo que no existía un recurso completo en línea para este tipo de cosas en ese momento, por lo que básicamente terminamos elaborando una lista nosotros mismos, revisando cosas como la guía telefónica (presionada por espacio allí, ¡las direcciones están abreviadas de muchas maneras! ).Como mencioné anteriormente, ¡te sorprenderá saber cuántos "duplicados" detectarás con solo unas pocas reglas comunes!

Recientemente me topé con una página con una información bastante completa lista de abreviaturas de direcciones, aunque es inglés americano, así que no estoy seguro de lo útil que sería en Alemania.Una búsqueda rápida en Google mostró un par de sitios, pero parecían trampas de suscripción a boletines informativos no deseados.Aunque fui yo quien buscó en Google en inglés, por lo que es posible que puedas buscar más con "abreviaturas de direcciones alemanas" en alemán :)

Otros consejos

Podrías usar el API de código geográfico de Google

Lo que de hecho da resultados para ambos ejemplos, simplemente lo probé.De esa manera obtienes resultados estructurados que puedes guardar en tu base de datos.Si la búsqueda falla, pídale al usuario que escriba la dirección de otra manera.

¡Cuanto antes puedas detener a la gente, más fácil será a largo plazo!

Al no estar muy familiarizado con su esquema de base de datos o formulario de entrada de datos, sugeriría una ruta similar a la siguiente:

  • tenga campos distintos en su base de datos para cada "parte" de dirección, p.calle, ciudad, código postal, Länder, etc.

  • Haga que su formulario de entrada de datos esté desglosado de manera similar, p.calle, ciudad, etc.

El razonamiento detrás de lo anterior es que cada parte probablemente tendrá sus propias "reglas" particulares para verificar direcciones ligeramente modificadas ("Quellenstrasse"->"Quellenstr.", "66/11"->"66a-11" arriba) para que su código de validación pueda verificar si los valores presentados para cada campo existen en su campo de base de datos respectivo.De lo contrario, puede tener una clase que aplique las reglas de transformación para cada campo determinado (p. ej."strasse" deriva de "str") y vuelve a comprobar si hay duplicados.

Obviamente el método anterior tiene sus inconvenientes:

  • puede ser lento, dependiendo de su conjunto de datos, dejando al usuario esperando

  • los usuarios pueden intentar evitarlo poniendo la dirección "Partes" en los campos incorrectos (agregando el código postal a la ciudad, etc.).pero por experiencia hemos descubierto que introducir incluso comprobaciones simples como la anterior evitará que un gran porcentaje de usuarios ingresen direcciones preexistentes.

Una vez que haya realizado la verificación básica, puede considerar optimizar los accesos a la base de datos requeridos, refinar las reglas, etc. para cumplir con su esquema particular.También puedes echar un vistazo a Función match() de MySQL para elaborar textos similares.

Antes de comenzar a buscar direcciones duplicadas en su base de datos, primero debe asegurarse de almacenar las direcciones en un formato estándar.

La mayoría de los países tienen una forma estándar de formatear direcciones; en EE. UU. es el sistema USPS CASS: http://www.usps.com/ncsc/addressservices/certprograms/cass.htm

Pero la mayoría de los demás países tienen un servicio/estándar similar.Pruebe este sitio para obtener más formatos internacionales:http://bitboost.com/ref/international-address-formats.html

Esto no sólo ayuda a encontrar duplicados, sino que también le ahorra dinero al enviar correos a sus clientes (el servicio postal cobra menos si la dirección está en un formato estándar).

Dependiendo de su aplicación, en algunos casos es posible que desee almacenar un registro de dirección "personalizado", así como el registro de dirección estándar.Esto mantiene contentos a sus clientes VIP.Una dirección "personalizada" podría ser algo como:

62 Oeste Noventa Primera Calle
Apartamento 4D
Manhattan, Nueva York, NY 10001

Mientras que la dirección estándar podría verse así:

62 W 91ST ST APARTAMENTO 4D
NUEVA YORK NY 10024-1414

Una cosa que quizás quieras ver es sonidoex búsquedas, que son bastante útiles para errores ortográficos y contracciones.

Sin embargo, esto no es una validación en la base de datos, por lo que puede que sea o no lo que está buscando.

Otra posible solución (suponiendo que realmente necesite datos de direcciones confiables y que no esté usando direcciones simplemente como una forma de evitar cuentas duplicadas) es utilizar un servicio web de terceros para estandarizar las direcciones proporcionadas por sus usuarios.

Funciona de esta manera: su sistema acepta la dirección de un usuario a través de un formulario en línea.Su formulario entrega la dirección del usuario al servicio web de estandarización de direcciones de terceros.El servicio web le devuelve la misma dirección pero ahora con los datos estandarizados en campos de dirección discretos y con las abreviaturas y formatos estándar aplicados.Su aplicación muestra esta dirección estandarizada a su usuario para su confirmación antes de intentar guardar los datos en su base de datos.

Si todas las direcciones de usuario pasan por un paso de estandarización y solo las direcciones estandarizadas se guardan en su base de datos, entonces la búsqueda de registros duplicados debería simplificarse enormemente ya que ahora está comparando manzanas con manzanas.

Uno de esos servicios de terceros es Servicio interactivo de Global Address que incluye a Alemania en la lista de países admitidos y también tiene una demostración en línea que demuestra cómo funciona su servicio (el enlace de demostración se puede encontrar en esa página web).

Obviamente, este enfoque tiene una desventaja de costos.Sin embargo, en el lado positivo:

  1. No necesitaría crear ni mantener sus propios metadatos de estandarización de direcciones.
  2. no necesitará mejorar continuamente sus rutinas de estandarización de direcciones, y
  3. Eres libre de centrar tu energía de desarrollo de software en las partes de la aplicación que sean exclusivas de tus necesidades.

Descargo de responsabilidad:No trabajo para Global Address y no he intentado utilizar su servicio.Simplemente los menciono como ejemplo, ya que tienen una demostración en línea con la que puedes jugar.

Para agregar una respuesta a mi propia pregunta:

Una forma diferente de hacerlo es pedir a los usuarios su número de teléfono móvil y enviarles un mensaje de texto para su verificación.Esto evita que la mayoría de la gente juegue con direcciones duplicadas.

Hablo por experiencia personal.(gracias cerdo !) Introdujeron la confirmación a través del teléfono móvil.¡Eso me impidió tener 2 cuentas!:-)

Me doy cuenta de que la publicación original es específica para direcciones alemanas, pero esta es una buena pregunta para direcciones en general.

En Estados Unidos, hay una parte de una dirección llamada código de barras del punto de entrega.Es un número único de 12 dígitos que identifica un único punto de entrega y puede servir como identificador único de una dirección.Para obtener este valor, querrá utilizar una API de servicio web de verificación de dirección o estandarización de dirección, que puede costar alrededor de $20/mes dependiendo del volumen de solicitudes que le realice.

En aras de una divulgación completa, soy el fundador de SmartyStreets.Ofrecemos tal API de servicio web de validación de direcciones llamado LiveAddress.Eres más que bienvenido a contactarme personalmente si tienes alguna pregunta.

El aprendizaje automático y la IA tienen algoritmos para encontrar similitudes de cadenas y medidas duplicadas.

El enlace de registro o la tarea de coincidir los registros equivalentes que difieren sintácticamente: se exploró por primera vez a fines de los años cincuenta y sesenta.

Puede representar cada par de registros utilizando un vector de características que describen la similitud entre los campos de registro individuales.

Por ejemplo, la detección duplicada adaptativa utilizando medidas de similitud de cadena aprendible.Por ejemplo, lee este documento

  1. Puede utilizar métricas de distancia genéricas o ajustadas manualmente para estimar la similitud de posibles duplicados.

  2. Puede utilizar algoritmos adaptables de coincidencia de nombres, como la métrica Jaro, que se basa en el número y el orden de los caracteres comunes entre dos cadenas.

  3. Distancia híbrida y basada en tokens.En tales casos, podemos convertir las cadenas S y T a Token Multisets (donde cada token es una palabra) y considerar métricas de similitud en estos múltiples conjuntos.

A menudo se utilizan restricciones en una base de datos para garantizar que los datos sean "únicos" en el sentido de la base de datos.

En cuanto a los "isomorfismos", creo que estás solo, es decir, escribes el código tú mismo.Si está en la base de datos, podría usar un disparador.

Estoy buscando una respuesta dirigida a direcciones de Estados Unidos.

El problema en cuestión es evitar que los usuarios ingresen duplicados como

Quellenstrasse 66/11 y Quellenstr. 66a-11

Esto sucede cuando permite que su usuario ingrese la dirección completa en el cuadro de entrada.

Existen algunos métodos que puede utilizar para evitar esto.

1.Formato uniforme usando RegEx

  • Puede solicitar a los usuarios que ingresen los detalles en un formato uniforme.
  • Eso es muy eficiente al realizar consultas también.
  • pruebe el valor ingresado por el usuario con algunas expresiones regulares y, si falla, solicite al usuario que lo corrija.

2.Utilice una API de mapas como Google Maps y solicite al usuario que seleccione detalles de ella.

  • Si elige Google Maps, puede lograrlo mediante codificación geográfica inversa.

De Guía para desarrolladores de Google,

El término geocodificación generalmente se refiere a traducir una dirección legible por humanos a una ubicación en un mapa. El proceso de hacer lo contrario, traducir una ubicación en el mapa a una dirección legible por humanos, se conoce como geocodificación inversa.

3.Permita datos heterogéneos como se muestra en la pregunta y compárelos con diferentes formatos.

  • En la pregunta, el OP permite direcciones en diferentes formatos.
  • En tal caso, puede cambiarlo a diferentes formas y verificarlo con la base de datos para obtener una solución.
  • Esto puede llevar más tiempo y el tiempo depende completamente de la cantidad de casos de prueba.

4.Divida la dirección en diferentes partes, guárdela en la base de datos y proporcione dicho formulario al usuario.

  • Es decir, proporciona diferentes campos para almacenar la calle, la ciudad, el estado, etc. en la base de datos.
  • También proporcione los diferentes campos de entrada al usuario para que ingrese la calle, ciudad, estado, etc. en formato de arriba hacia abajo.
  • Cuando el usuario ingresa al estado, limite la consulta para encontrar incautos solo a ese estado.
  • Cuando el usuario ingrese la ciudad, limítelo a esa ciudad únicamente.
  • Cuando el usuario ingrese a la calle, limítela a esa calle.

Y finalmente

  • Cuando el usuario ingrese la dirección, cámbiela a diferentes formatos y pruébela con la base de datos.

Esto es eficiente, incluso si la cantidad de casos de prueba puede ser alta, la cantidad de entradas que pruebe será muy menor y, por lo tanto, consumirá menos tiempo.

En EE. UU., puedes usar USPS Herramienta web de estandarización de direcciones.Verifica y normaliza las direcciones por usted.De esta manera, puedes normalizar la dirección antes de verificar si ya existe en la base de datos.Si todas las direcciones de la base de datos ya están normalizadas, podrá detectar duplicados fácilmente.

URL de muestra:

https://production.shippingapis.com/ShippingAPI.dll?API=Verify&XML=insert_request_XML_here

Solicitud de muestra:

<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>

Respuesta de muestra:

<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>

Otros países pueden tener sus propias API.Otras personas mencionaron API de terceros que admiten varios países y que podrían resultar útiles en algunos casos.

Como Google busca sugerencias para la búsqueda, puede buscar campos de direcciones de bases de datos

Primero, creemos un archivo 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>

Ahora crearemos un archivo city.php que agregará nuestra consulta a MySQL DB y dará respuesta como JSON.Aquí está el código:

<?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);
}

?>

y luego evitar guardarlos en la base de datos si se encuentran duplicados en la columna de la tabla

Y para su código 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');
    }
?>

Haga coincidir la dirección con las direcciones proporcionadas por DET BundesPost para detectar duplicados.

DET probablemente vende un CD como lo hace EE.UU.El problema es entonces la correspondencia con las direcciones del Bundespost.Sólo un largo proceso de sustitución de abreviaturas por abreviaturas aprobadas posteriormente y demás.

Lo mismo en Estados Unidos.Haga coincidir las direcciones de la oficina de correos de EE. UU. (lo siento, cuestan dinero, por lo que los CD que no están completamente abiertos están disponibles en la oficina de correos de EE. UU.) para encontrar duplicados.

Esta es una vieja pregunta, pero otro enfoque es calcular la distancia de Levenshtein a las direcciones y de esta manera puede encontrar direcciones ya existentes que sean muy similares.Puedes ver más aquí. Encontrar direcciones duplicadas utilizando la métrica de distancia de Levenshtein en SQL.

En mi opinión, suponiendo que ya tenía muchos datos sucios en su base de datos,

Tienes que construir tu filtro sucio "hecho a mano" que pueda detectar un máximo de abreviatura alemana...

Pero si tratas muchos datos, correrás el riesgo de encontrar alguna muestra falsa positiva y verdadera negativa...

Finalmente, un trabajo semiautomatizado (máquina con asistencia humana cuando la probabilidad de un caso de falso positivo o verdadero negativo es demasiado alta) será la mejor solución.

Cuanto más trate la "excepción" (porque los humanos generan una excepción al completar los datos), más se ajustará su filtro "hecho a mano" a sus necesidades.

Por otro lado, también puedes utilizar un servicio de verificación de direcciones de Alemania del lado del usuario y almacenar solo la verificada...

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top