在Salesforce中优化Levenshtein距离算法

时间:2012-04-18 13:59:58

标签: multidimensional-array salesforce apex-code levenshtein-distance

我有一个名为customer的自定义对象,其中包含Customer_Name,Address_Line_1,Post_Code等字段。

我想浏览所有记录并比较Customer_Name的相似性(基于模糊搜索或levenshtein距离)。如果相似度高于或低于某个阈值,则会更新自定义字段(Possible_Duplicate_Customer_ID__c)以识别可能的副本。

我设法实现了这个,但我遇到了两个问题:

1)。超过Salesforce govenor限制(太多脚本声明:200001)可能是由Levenshtein距离算法所需的大量循环引起的。 2)。我提交的列表(newList)也包含重复的ID。

    private static List<Customer__c> newList = new List<Customer__c>();

webService static Integer findDupes() {

    Integer returnCount = 0;
    Double cost = 0;
    Integer COST_THRESHOLD = 5;

    Map<id,Customer__c> cMap = new Map<id,Customer__c>([
        select ID, Name, Customer_Name__c, Possible_Duplicate_Customer_ID__c 
        from Customer__c 
    ]);

    List<Customer__c> custList1 = cMap.values();        
    List<Customer__c> custList2 = custList1.clone();

    for (Customer__c cust1 :custList1) {
        for (Customer__c cust2 :custList2) {
            cost = LevenshteinDistance.computeLevenshteinDistance(
                    cust1.Customer_Name__c, cust2.Customer_Name__c);
                if(cost<COST_THRESHOLD && cost != 0) {
                    Customer__c c = new Customer__c(
                        id = cust2.Id, 
                        Possible_Duplicate_Customer_ID__c = cust1.Name
                    );
                    newList.add(c);
                }
                System.debug(cost+' edits to transform '
                        +cust1.Customer_Name__c+' to '+cust2.Customer_Name__c);
        }
    }

    returnCount = newList.size();

    update newList;        
    return returnCount;
}

3 个答案:

答案 0 :(得分:1)

您是否尝试了getLevenshteinDistance的新String method

另请参阅我的问题/方法here。我通过坚持只返回同一国家/地区的匹配邮件代码或城市来保持初始匹配数量。

答案 1 :(得分:0)

我建议在使用batchable接口的类中运行代码,这更适合处理大量数据。由于您的Web服务不接受输入,您可以按计划每小时运行批处理,通过标记记录标记dupes,然后在Web服务中提取这些记录。当然,如果你需要它实时,你需要优化这个循环。

对于更新列表中的重复ID,您使用cust2.Id进行更新应考虑到这一点,但您似乎无法防范将客户记录与自身进行比较的情况!这应该解决它:

for (Customer__c cust1 :custList1) {
    for (Customer__c cust2 :custList2) {
        if (cust1.Id == cust2.Id) {
            continue;
        }

答案 2 :(得分:0)

Lev距离是模糊匹配的一个很好的工具,但由于脚本声明的限制,在Apex中基本上无法使用。使用我已经存在的版本(改编自旧版本的Apex Lang),将“0123456789”与“0246803579”进行比较需要700多个脚本语句。比较“实际资源使用情况与执行的代码行数基本无关” “是的,但令人讨厌的'少数'高级开发人员将允许我们在州长限制实施期间偷工减料”需要 60,000个脚本声明。除非你进行少量的小比较,或者以某种方式重写Lev以使脚本声明更友好,否则在平台上很难证明这一点。

我已经开始在Apex中使用更便宜的Lev代理,比如Soundex用于名称或短字比较,或者花哨的动态SOQL“LIKE”语句。如果你想要做的事情可以以某种方式被提炼成集合操作,那么那些让你在Apex中获得好成绩,因为.contains仅花费你一个脚本执行。

如果你真的需要做大量的Lev,你可能不得不求助于使用API​​或重写代码更紧凑。根据您的使用情况,将计算推入浏览器也可能是一种选择。