2016-07-06 49 views
0

检查两个具有多个属性的对象是否相似的最佳方法是什么?数据库中很多字符串的相似性

可以说我有一个对象 - 地址,其中有10个领域,如:LOCATION1,LOCATION2,LOCATION3,LOCATION4,...,POSTALCODE,所有者,居住者..

它们都存储在Postgres的数据基础为jsonb类型。

当新对象进来时,我需要检查是否有任何类似的地址。

这种情况下最常用的技术是什么?

一个想法是连接所有属性并检查levenshtein距离。

我现在没有被绑定到任何特定的技术,要求是这些对象可能很多,它们必须存储在某个地方。

+0

通常您会使用全文搜索索引,但我不确定这是否适用于Json数据。 –

回答

0

JSON和JSONB类型意味着具有不同含义标记的元素的数据。这通常意味着,这些不同的要素不能以完全相同的方式得到有效的处理,这进一步意味着一刀切的方法可能不会取得好的结果。

正如你所提到的那样,Levenshtein距离是一种可能的方法,但大多数情况下它必须以某种方式加权定制到您的特定数据,甚至可能不足以满足大多数实际情况数据集。

例如,考虑一些基本地址。匹配街道号码本身毫无意义。同上街道名称。真正的所有元素都是依赖的,只有从匹配的国家开始,通过州/省等进行下去时,“相似性”才具有真正的意义。简单的权重无法捕捉到这种类型的关系。

解决方案是使用存储过程来确定给定表中的行之间的相似性。虽然PL/pgSQL可以用于此(并且对于简单的表格可以很好地工作),但当事情变得复杂时,可能需要深入挖掘PL/Python之类的东西。当然,这些存储过程的效率与它们的写法有很大的不同,但即使在大型数据库中使用时,它们也可以很好地执行。

例如(而且也没有足够的信息在你的问题做出的东西,将直出在这里工作,所以请把这样的东西比伪要好一些,但不是彻底的测试PL/Python)的:

CREATE OR REPLACE FUNCTION compare_json_addresses(addr1 JSON, addr2 JSON) 
RETURNS INTEGER AS 
$$ 
BEGIN 
    import simplejson as json 
    a1, a2 = json.loads(addr1), json.loads(addr2) 
    similarity = 0 
    for unit in ('country', 'state', 'town', 'street', 'num'): 
     if a1[unit] != a2[unit]: 
      break 
     else: 
      similarity += 1 
    return similarity 
END; 
$$ 
LANGUAGE plpythonu STRICT IMMUTABLE; 

显然你必须修改它以考虑你正在使用的各种附加位置字段,并弄清楚你希望它们如何关联。

+0

感谢您的意见,实际上我决定使用elasticsearch来对数据进行索引,并通过主要字段对其进行过滤,并将它们与可能相似的字段进行匹配。所以它不知何故与你的答案相符。 – sandris