我有一个名为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;
}
答案 0 :(得分:1)
答案 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或重写代码更紧凑。根据您的使用情况,将计算推入浏览器也可能是一种选择。