在数据库中找到重复的地址,阻止用户提前输入它们?

问题描述 投票:16回答:16

如何在数据库中找到重复的地址,或者在填写表单时更好地阻止人们?我想越早越好?

是否有任何好的方法来抽象街道,邮政编码等,以便可以检测到错别字和简单的尝试获得2次注册?喜欢:

Quellenstrasse 66/11 
Quellenstr. 66a-11

我在说德语地址......谢谢!

database sanitization street-address
16个回答
4
投票

约翰:

@PConroy:这也是我最初的thougt。有趣的是,要找到地址不同部分的良好转换规则!有什么好建议吗?

当我们之前处理这类项目时,我们的方法是采用我们现有的地址语料库(150k左右),然后对我们的域应用最常见的转换(爱尔兰,所以“Dr” - >“Drive”,“ Rd“ - >”Road“等)。我担心当时没有全面的在线资源可用,所以我们自己最终基本上都会列出一个列表,检查电话簿之类的东西(按空格键,地址以各种方式缩写! )。正如我之前提到的,只要加上一些常用规则,你就会惊讶地发现有多少“重复”!

我最近偶然发现了一个相当全面的list of address abbreviations页面,虽然它是美国英语,所以我不确定它在德国有多大用处!一个快速的谷歌出现了几个网站,但他们似乎垃圾邮件通讯注册陷阱。虽然那是我用英语搜索谷歌,所以你可能会更多地看看德语中的“德语地址缩写”:)


0
投票

通常,您在数据库中使用约束来确保数据在基于数据的意义上是“唯一的”。

关于“同构”,我认为你是独立的,即自己编写代码。如果在数据库中,您可以使用触发器。


0
投票

我正在寻找解决美国地址问题的答案

有问题的是阻止用户输入重复项

Quellenstrasse 66/11Quellenstr. 66a-11

当您让用户在输入框中输入完整地址时会发生这种情况。

您可以使用一些方法来防止这种情况发生。

1. Uniform formatting using RegEx

  • 您可以提示用户以统一格式输入详细信息。
  • 查询时也非常有效
  • 测试用户对某些正则表达式输入的值,如果失败,请让用户更正它。

2.Use a map api like google maps and ask the user to select details from it.

  • 如果您选择谷歌地图,您可以使用反向地理编码实现它。

来自Google Developer's guide

术语地理编码通常是指将人类可读地址翻译成地图上的位置。执行相反的过程,将地图上的位置转换为人类可读的地址,称为反向地理编码。

3. Allow heterogeneous data as shown in the question and compare it with different formatting.

  • 在问题中,OP允许以不同格式的地址。
  • 在这种情况下,您可以将其更改为不同的表单并与数据库一起检查以获得解决方案。
  • 这可能需要更多时间,时间完全取决于测试用例的数量。

4. Split the address into different parts and store it in db and provide such a form to user.

  • 这提供了在数据库中存储街道,城市,州等的不同字段。
  • 还为用户提供不同的输入字段,以自上而下的格式输入街道,城市,州等。
  • 当用户输入state时,缩小查询范围以仅查找到该状态的dupe。
  • 当用户进入城市时,仅将其缩小到该城市。
  • 当用户进入街道时,将其缩小到该街道。

最后

  • 当用户输入地址时,将其更改为不同的格式并根据数据库进行测试。

即使测试用例的数量可能很高,这也是有效的,您测试的条目数将非常少,因此它将消耗非常少的时间。


0
投票

在美国,您可以使用USPS Address Standardization Web Tool。它会为您验证和规范化地址。这样,您可以在检查地址是否已存在于数据库之前规范化地址。如果数据库中的所有地址都已经规范化,您将能够轻松地发现重复数据。

示例网址:

https://production.shippingapis.com/ShippingAPI.dll?API=Verify&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,在某些情况下可能会有用。


0
投票

谷歌搜索搜索建议,您可以搜索数据库地址字段

首先,让我们创建一个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 DB并作为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');
    }
?>

0
投票

将地址与DET BundesPost提供的地址进行匹配,以检测重复项。

DET可能像美国一样销售CD。然后问题变得与Bundespost地址匹配。只需用后期批准的缩写等替换缩写即可。

同样在美国。匹配USPostOffice地址(对不起这些花钱,所以它不是完全开放的CD可以从美国邮局获得)找到重复。


0
投票

这是一个老问题,但另一种方法是计算Levenshtein到地址的距离,这样你就可以找到非常相似的现有距离。你可以在这里看到更多。 Finding Duplicate Addresses Using the Levenshtein Distance Metric in SQL.


-1
投票

在我看来,假设你的数据库中已经有很多脏数据,

你必须建立你的“手工”脏过滤器,可以检测到最大的德国缩减...

但如果您处理大量数据,您将冒险找到一些假阳性和真阴性样本......

最后一个半自动化的工作(当假阳性或真阴性的概率太高时,人工辅助的机器)将是最佳解决方案。

更多你对待“异常”(因为填充数据时人为引发异常),更多的“手工”过滤器将适合您的需求。

另一方面,您也可以在用户端使用德国地址验证服务,并仅存储已验证的服务...


10
投票

你可以使用Google GeoCode API

事实上,这两个例子都给出了结果,只是试了一下。这样您就可以获得可以保存在数据库中的结构化结果。如果查找失败,请要求用户以其他方式编写地址。


6
投票

你越早阻止别人,从长远来看就越容易!

不太熟悉您的数据库架构或数据输入表单,我建议一个类似如下的路由:

  • 数据库中为每个地址“部分”设置不同的字段,例如街道,城市,邮政编码,Länder等
  • 将您的数据输入表单分类,例如街道,城市等

上述背后的原因是每个部分都可能有自己特定的“规则”来检查稍微改变的地址,(“Quellenstrasse” - >“Quellenstr。”,“66/11” - >“66a-11”)因此,验证代码可以检查每个字段的值是否存在于各自的db字段中。如果没有,您可以拥有一个类,为每个给定的字段应用转换规则(例如“strasse”被阻止为“str”)并再次检查重复项。

显然上面的方法有它的缺点:

  • 它可能很慢,具体取决于您的数据集,让用户等待
  • 用户可以尝试通过将地址“部件”放在错误的字段中(将邮政代码附加到城市等)来绕过它。但从经验来看,我们发现即使是如上所述的简单检查,也会阻止大部分用户输入预先存在的地址。

完成基本检查后,您可以查看优化所需的数据库访问,优化规则等以满足您的特定模式。你也可以看一下MySQL's match() function来制作类似的文字。


2
投票

在开始在数据库中搜索重复地址之前,应首先确保以标准格式存储地址。

大多数国家都有标准格式化地址,在美国它是USPS CASS系统:http://www.usps.com/ncsc/addressservices/certprograms/cass.htm

但大多数其他国家/地区也有类似的服务/标准。尝试使用此网站获取更多国际格式:http://bitboost.com/ref/international-address-formats.html

这不仅有助于查找重复项,还可以在邮寄给客户时节省资金(如果地址是标准格式,邮政服务费用会减少)。

根据您的应用程序,在某些情况下,您可能希望存储“虚荣”地址记录以及标准地址记录。这可以让您的VIP客户满意。 “虚荣”地址可能是这样的:

西九十一街62号 4D公寓 曼哈顿,纽约,NY 10001

虽然标准地址可能如下所示:

62 W 91ST ST APT 4D 纽约纽约10024-1414


2
投票

你可能想要看的一件事是Soundex搜索,它对拼写错误和收缩非常有用。

然而,这不是数据库内验证,因此它可能或可能不是您正在寻找的。


2
投票

另一种可能的解决方案(假设您确实需要可靠的地址数据,并且您不仅仅使用地址作为防止重复帐户的方法)是使用第三方Web服务来标准化用户提供的地址。

它以这种方式工作 - 您的系统通过在线表单接受用户的地址。您的表单将用户的地址移交给第三方地址标准化Web服务。 Web服务为您提供相同的地址,但现在将数据标准化为离散地址字段,并应用标准缩写和格式。在尝试将数据保存到数据库之前,您的应用程序会向您的用户显示此标准化地址以进行确认。

如果所有用户地址都经过标准化步骤并且只有标准化地址保存到您的数据库中,那么应该大大简化查找重复记录,因为您现在正在比较苹果和苹果。

其中一个第三方服务是Global Address's Interactive Service,其中包括德国在受支持国家/地区的列表,还有一个在线演示,演示了他们的服务如何工作(演示链接可以在该网页上找到)。

显然,这种方法存在成本劣势。但是,从好的方面来说:

  1. 您不需要创建和维护自己的地址标准化元数据
  2. 您不需要不断增强地址标准化例程,并且
  3. 您可以将软件开发的精力集中在应用程序中满足您要求的部分

免责声明:我不为Global Address工作,也没有尝试使用他们的服务。我只是提到它们作为一个例子,因为它们有一个你可以实际玩的在线演示。


1
投票

要为我自己的问题添加答案:

一种不同的方式是询问用户的手机号码,向他们发送文本消息以进行验证。这可以阻止大多数人弄乱重复的地址。

我是从个人经历谈起的。 (感谢pigsback!)他们通过手机推出了确认。这阻止了我有2个帐户! :-)


1
投票

我意识到原始帖子是特定于德语地址的,但这对于一般地址来说是一个很好的问题。

在美国,有一个称为交付点条形码的地址的一部分。它是一个唯一的12位数字,用于标识单个交付点,并可用作地址的唯一标识符。要获得此值,您需要使用地址验证或地址标准化Web服务API,根据您对其提出的请求量,每个服务器的成本约为20美元。

为了充分披露,我是SmartyStreets的创始人。我们提供了一个名为LiveAddress的address validation web service API。如果您有任何问题,我们非常欢迎您亲自与我联系。


1
投票

机器学习和AI具有查找字符串相似性和重复度量的算法。

记录链接或匹配语法不同的等效记录的任务 - 在20世纪50年代末和60年代首次被探索。

您可以使用描述各个记录字段之间相似性的特征向量来表示每对记录。

例如,使用可学习字符串相似性度量的自适应重复检测。例如,read this doc

  1. 您可以使用通用或手动调整的距离指标来估计潜在重复项的相似性。
  2. 您可以使用自适应名称匹配算法,例如Jaro metric,它基于两个字符串之间的公共字符的数量和顺序。
  3. 基于令牌和混合距离。在这种情况下,我们可以将字符串s和t转换为令牌多个集合(其中每个令牌都是一个单词)并考虑这些多集合上的相似性度量。
© www.soinside.com 2019 - 2024. All rights reserved.