如何在数据库中找到重复的地址,或者在填写表格时更好地阻止人们?估计越早越好?
是否有任何抽象街道、邮政编码等的好方法,以便可以检测到拼写错误和获取 2 个注册的简单尝试?像:
Quellenstrasse 66/11
Quellenstr. 66a-11
我说的是德国地址...谢谢!
如何在数据库中找到重复的地址,或者在填写表格时更好地阻止人们?估计越早越好?
是否有任何抽象街道、邮政编码等的好方法,以便可以检测到拼写错误和获取 2 个注册的简单尝试?像:
Quellenstrasse 66/11
Quellenstr. 66a-11
我说的是德国地址...谢谢!
您可以使用Google GeoCode API
实际上,它为您的两个示例都给出了结果,只是尝试了一下。这样您就可以获得可以保存在数据库中的结构化结果。如果查找失败,要求用户以另一种方式写入地址。
越早阻止人们,从长远来看就越容易!
不太熟悉您的数据库架构或数据输入表单,我建议使用类似以下的路线:
每个地址“部分”在您的数据库中都有不同的字段,例如街道、城市、邮政编码、Länder 等。
将您的数据输入表格进行类似分解,例如街道、城市等
上述原因是每个部分可能都有自己特定的“规则”,用于检查稍微更改的地址(“Quellenstrasse”->“Quellenstr.”、“66/11”->“66a-11”)因此您的验证代码可以检查为每个字段显示的值是否存在于它们各自的数据库字段中。如果没有,你可以有一个类为每个给定字段应用转换规则(例如,“strasse”源于“str”)并再次检查重复项。
显然上述方法有它的缺点:
它可能很慢,具体取决于您的数据集,让用户等待
用户可能会尝试通过将地址“部分”放在错误的字段中(将邮政编码附加到城市等)来绕过它。但根据经验,我们发现即使像上面那样引入简单的检查也会阻止大部分用户输入预先存在的地址。
完成基本检查后,您可以查看优化所需的数据库访问、改进规则等以满足您的特定模式。您还可以查看MySQL 的 match() 函数来计算类似的文本。
约翰内斯:
@PConroy:这也是我最初的想法。有趣的部分是为地址的不同部分找到好的转换规则!有什么好的建议吗?
当我们之前从事此类项目时,我们的方法是采用我们现有的地址语料库(150k 左右),然后对我们的域应用最常见的转换(爱尔兰,所以“博士”->“驱动器”,“路”->“路”等)。恐怕当时没有全面的在线资源,所以我们最终基本上是自己想出了一个清单,检查电话簿之类的东西(那里的空间,地址被各种缩写方式! )。正如我之前提到的,您会惊讶地发现,只需添加一些常见规则,您就会检测到多少“重复”!
我最近偶然发现了一个页面,其中包含相当全面的地址缩写列表,虽然它是美式英语,所以我不确定它在德国有多大用处!一个快速的谷歌出现了几个网站,但它们看起来像是垃圾邮件通讯注册陷阱。虽然那是我用英语谷歌搜索,所以你可能会更多地看一下德语中的“德国地址缩写”:)
在开始在数据库中搜索重复地址之前,您应该首先确保以标准格式存储地址。
大多数国家/地区都有格式化地址的标准方式,在美国是 USPS CASS 系统:http ://www.usps.com/ncsc/addressservices/certprograms/cass.htm
但大多数其他国家/地区都有类似的服务/标准。试试这个网站了解更多国际格式: http ://bitboost.com/ref/international-address-formats.html
这不仅有助于查找重复项,而且还可以在邮寄客户时为您节省金钱(如果地址采用标准格式,邮政服务会收取更少的费用)。
根据您的应用程序,在某些情况下,您可能希望存储“虚名”地址记录以及标准地址记录。这让您的 VIP 客户满意。“虚荣”地址可能类似于:
62 West Ninety First Street
公寓 4D
曼哈顿, 纽约, NY 10001
虽然标准地址可能如下所示:
62 W 91ST ST APT 4D
纽约 NY 10024-1414
您可能想要查看的一件事是Soundex搜索,它对于拼写错误和缩略语非常有用。
但是,这不是数据库内验证,因此它可能是也可能不是您要查找的内容。
另一种可能的解决方案(假设您实际上需要可靠的地址数据,并且您不只是使用地址来防止重复帐户)是使用第三方网络服务来标准化您的用户提供的地址。
它以这种方式工作——您的系统通过在线表格接受用户的地址。您的表单将用户地址移交给第三方地址标准化 Web 服务。Web 服务为您返回相同的地址,但现在将数据标准化为离散的地址字段,并应用标准缩写和格式。在尝试将数据保存到数据库中之前,您的应用程序会向您的用户显示此标准化地址以供他们确认。
如果所有用户地址都经过标准化步骤并且只有标准化地址保存到您的数据库中,那么查找重复记录应该会大大简化,因为您现在正在比较苹果和苹果。
此类第三方服务之一是Global Address 的交互式服务,它在受支持的国家/地区列表中包括德国,并且还有一个在线演示,演示了他们的服务如何工作(可以在该网页上找到演示链接)。
显然,这种方法存在成本劣势。但是,从好的方面来说:
免责声明:我不为 Global Address 工作,也没有尝试使用他们的服务。我只是将它们作为示例提及,因为它们有一个您可以实际玩的在线演示。
要为我自己的问题添加答案:
另一种方法是询问用户他们的手机号码,向他们发送短信以进行验证。这可以阻止大多数人弄乱重复的地址。
我说的是个人经历。(感谢pigsback!)他们介绍了通过手机确认。这阻止了我拥有 2 个帐户!:-)
我意识到原始帖子是针对德国地址的,但对于一般地址来说,这是一个很好的问题。
在美国,地址中有一部分称为收货点条形码。这是一个唯一的 12 位数字,用于标识单个交付点,并可用作地址的唯一标识符。要获得此值,您需要使用地址验证或地址标准化 Web 服务 API,根据您向其发出的请求量,其成本约为 20 美元/月。
为了全面披露,我是 SmartyStreets 的创始人。我们提供了一个名为 LiveAddress的地址验证 Web 服务 API 。如果您有任何问题,我们非常欢迎您亲自与我联系。
机器学习和人工智能具有查找字符串相似性和重复度量的算法。
记录链接或匹配语法不同的等效记录的任务——在 1950 年代后期和 1960 年代首次被探索。
您可以使用描述各个记录字段之间相似性的特征向量来表示每对记录。
例如,使用可学习字符串相似性度量的自适应重复检测。例如,阅读这个文档
您可以使用通用或手动调整的距离度量来估计潜在重复的相似性。
您可以使用自适应名称匹配算法,例如 Jaro 度量,它基于两个字符串之间常见字符的数量和顺序。
基于令牌和混合距离。在这种情况下,我们可以将字符串 s 和 t 转换为标记多集(其中每个标记是一个单词),并考虑这些多集的相似性度量。
通常,您在数据库中使用约束来确保数据在基于数据的意义上是“唯一的”。
关于“同构”,我认为您是靠自己的,即您自己编写代码。如果在数据库中,您可以使用触发器。
我正在寻找解决美国地址的答案
有问题的问题是防止用户输入重复项,例如
Quellenstrasse 66/11
和Quellenstr. 66a-11
当您让用户在输入框中输入完整地址时,就会发生这种情况。
您可以使用一些方法来防止这种情况发生。
来自谷歌开发者指南,
术语地理编码通常是指将人类可读的地址翻译成地图上的位置。相反的过程,将地图上的位置转换为人类可读的地址,称为反向地理编码。
最后
即使测试用例的数量可能很高,这也是有效的,您测试的条目数量将非常少,因此它会消耗非常少的时间。
在美国,您可以使用 USPS地址标准化 Web 工具。它为您验证和规范化地址。这样,您可以在检查地址是否已存在于数据库中之前对其进行规范化。如果数据库中的所有地址都已标准化,您将能够轻松发现重复项。
示例网址:
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。其他人提到了支持多个国家/地区的 3rd 方 API,这在某些情况下可能有用。
作为 google fetch suggesions for search,您可以搜索数据库地址字段
首先,让我们创建一个 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');
}
?>
将地址与 DET BundesPost 提供的地址匹配以检测重复。
DET 可能像美国一样销售 CD。然后问题就变成了与联邦邮政地址匹配。只是用批准的缩写等替换缩写的漫长过程。
在美国也是这样。匹配美国邮局地址(抱歉,这些要花钱,所以它不是完全开放的 CD 可从美国邮局获得)以查找重复项。
在我看来,假设您的数据库中已经有很多脏数据,
你必须建立你的“手工”脏过滤器,它可以检测到最多的德语缩写......
但是如果你处理大量数据,你会冒险找到一些假阳性和真阴性样本......
最后,一个半自动化的工作(当假阳性或真阴性的概率太高时有人工协助的机器)将是最好的解决方案。
您处理“异常”的次数越多(因为在填充数据时人为引发异常),您的“手工”过滤器就越适合您的要求。
另一方面,您也可以在用户端使用德国地址验证服务,并且只存储经过验证的地址...