function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Brandon Hurley 5Brandon Hurley 5 

Datacloud.FindDuplicates.findduplicates(accountInsertList).size() always equals 1 - help

I'm trying to insert an account record if it's not a duplicate. I'm referencing the findDuplicates method documentation found here: link (https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_class_Datacloud_FindDuplicates.htm#apex_Datacloud_FindDuplicates_methods

Account acct = new Account();
acct.Name = 'Acme';
acct.BillingStreet = '123 Fake St';
acct.BillingCity = 'Springfield';
acct.BillingState = 'VT';
acct.BillingCountry = 'US';
        
List<Account> acctList = new List<Account>();
acctList.add(acct); 

if (Datacloud.FindDuplicates.findDuplicates(acctList).size() ​== 0) {
// If the new account doesn't have duplicates, insert it.
    insert(acct);
}
Here is my code:
trigger clientImportTrigger on Client_Import__c (before insert) {
    List<Account> accountsToInsert = new List<Account>();
    Id personAccRecTypeId = Schema.SObjectType.Account.getRecordTypeInfosByDeveloperName().get('PersonAccount').getRecordTypeId();
    
    for (Client_Import__c A : trigger.new){
//create personAccount
        List<Account> dupeTestPersonAcc = new List<Account>();
        string pAddress = (A.addressLine1__c + ', '+ A.addressLine2__c);
                
        Account newPersonAcc = new Account();
        	newPersonAcc.FirstName = A.firstName__c;
            newPersonAcc.LastName = A.lastName__c;
            newPersonAcc.PersonEmail= A.email__c;
            newPersonAcc.Phone = A.phone__c;
            newPersonAcc.Phone_Type__c = A.phoneType__c;
            newPersonAcc.PersonMailingStreet = pAddress;        	
            newPersonAcc.PersonMailingcity = A.City__c;
            newPersonAcc.PersonMailingState = A.State__c;
            newPersonAcc.PersonMailingPostalCode = A.Zip__c;
            newPersonAcc.PersonMailingCountry = A.Country__c;
            newPersonAcc.Language_Preference__c = A.Language__c;
        	newPersonAcc.RecordTypeId = personAccRecTypeId;
        	dupeTestPersonAcc.add(newPersonAcc); 
        	//accountsToInsert.add(newPersonAcc);
        
        //if the new person account doesn't have duplicates, put it in the list to be inserted later with the rest
        System.debug(Datacloud.FindDuplicates.findDuplicates(dupeTestPersonAcc).size());
        if (Datacloud.FindDuplicates.findDuplicates(dupeTestPersonAcc).size() == 0){
        	accountsToInsert.add(newPersonAcc);
        	
        }
    }
    insert(accountsToInsert);
}

​​​​​​The problem I'm having is the findDuplicates(sObject).size() is always equal to 1, instead of 0 when I run the test class that just inserts a single record. Bascially, I can't figure out how to create the "if statement" so that a record is inserted if no duplicate is found. Any help is appreciated.
Best Answer chosen by Brandon Hurley 5
David Zhu 🔥David Zhu 🔥
You may use the following code to get duplicate match.  

public static Boolean CheckIfMatch(List<sObject> sObjectList)
{
Boolean isMatch = false;
List<Datacloud.FindDuplicatesResult> results = Datacloud.FindDuplicates.findDuplicates(sObjectList);
for (Datacloud.FindDuplicatesResult findDupeResult : results)  {
    for (Datacloud.DuplicateResult dupeResult : findDupeResult.getDuplicateResults()) {
        string rule = dupeResult.getDuplicateRule();
        for (Datacloud.MatchResult matchResult : dupeResult.getMatchResults()) {
            if (matchResult.getMatchRecords().size() > 0) { 
                isMatch = true;
            }
        }
    }
}}


I think there is an issue in your trigger. To Insert Account from Client_Import__c object, AFTER trigger should be used. You are using Before trigger.
 

All Answers

David Zhu 🔥David Zhu 🔥
You may use the following code to get duplicate match.  

public static Boolean CheckIfMatch(List<sObject> sObjectList)
{
Boolean isMatch = false;
List<Datacloud.FindDuplicatesResult> results = Datacloud.FindDuplicates.findDuplicates(sObjectList);
for (Datacloud.FindDuplicatesResult findDupeResult : results)  {
    for (Datacloud.DuplicateResult dupeResult : findDupeResult.getDuplicateResults()) {
        string rule = dupeResult.getDuplicateRule();
        for (Datacloud.MatchResult matchResult : dupeResult.getMatchResults()) {
            if (matchResult.getMatchRecords().size() > 0) { 
                isMatch = true;
            }
        }
    }
}}


I think there is an issue in your trigger. To Insert Account from Client_Import__c object, AFTER trigger should be used. You are using Before trigger.
 
This was selected as the best answer
Brandon Hurley 5Brandon Hurley 5

Hmm... I'm not really sure why an "after trigger" would affect anything here. I'm not referencing the custom object Client_Import__c.Id on the Account being created, nor do they have any lookup or master-detail relationships, so it's not necessary to insert the Client_Import__c before inserting the Account records. Also, the Accounts will get created just fine if i change the duplicate criteria from

(Datacloud.FindDuplicates.findDuplicates(dupeTestPersonAcc).size() == 0)
to
(Datacloud.FindDuplicates.findDuplicates(dupeTestPersonAcc).size() == 1)

so the problem (or sysmptom of the problem) is that the findDuplicates method is always returning a size value of 1 instead of a 0.

The problem with that is, when i set the size() == 1, it doesn't stop duplicates in my tests. I can insert records with the same values for account fields that are referenced in the matching and duplicate rules, that would normally stop users from entering those records in the Account Page UI.

David Zhu 🔥David Zhu 🔥
(Datacloud.FindDuplicates.findDuplicates(dupeTestPersonAcc) returns details of matching rules of the object. you have one matching rule defined on account object. So, it returns 1. Datacloud.MatchResult is the place to check if there is matching for each rule.

It is the best practice to put such process in after trigger even though it won't affect result in your case. You may check sfdc documents to get more details.
Brandon Hurley 5Brandon Hurley 5
Thank you for that explanation. I believe that implies that the code on the salesforce documentation page is incorrect, or would not work as it is intended or implied (to prevent duplicates). It would only insert the record if the object does not have duplicate rules, not iduplicates?
Mike ArthurMike Arthur
I believe you're right Brandon, the docs are incorrect.  I will provide feedback on the docs page.

Meanwhile, hopefully you've resolved your issue by now, but for anyone else arriving here, here's some anon Apex that I wrote to figure out how to determine if there is a duplicate.
Run it with acct field values so that there is no duplicate then adjust the acct field values according to your duplicate rules so that it should find a duplicate and when you run it again you will see the difference in the debugs.
Note that I was testing against Person Account Duplicate Rules which matched on email and phone.
 
Account acct = new Account();
acct.Name = 'Acme';
acct.BillingStreet = '123 Fake St';
acct.BillingCity = 'Springfield';
acct.BillingState = 'VT';
acct.BillingCountry = 'US';
acct.RecordTypeId = SObjectType.Account.getRecordTypeInfosByDeveloperName().get('PersonAccount').getRecordTypeId();
acct.PersonEmail = 'mike@test.zzz';
acct.Phone = '07900123456';

List<Account> acctList = new List<Account>();
acctList.add(acct); 

// This is from the docs and looks to be incorrect:
if (Datacloud.FindDuplicates.findDuplicates(acctList).size() == 0) {
// If the new account doesn't have duplicates, insert it.
    System.debug('MA: No duplicates');
}

// This is how I determined if there is a duplicate:
for (Datacloud.FindDuplicatesResult duplicateResult : Datacloud.FindDuplicates.findDuplicates(acctList)) {
    for (Datacloud.DuplicateResult dr : duplicateResult.duplicateresults) {
        System.debug('MA: Duplicate Rule: ' + dr.getDuplicateRule());
        System.debug('MA: No of match results: ' + dr.getMatchResults().size());
        for (Datacloud.MatchResult mr : dr.getMatchResults()) {
            System.debug(mr.getMatchRecords().isEmpty() ? 'No Duplicates' : 'Duplicate Record:');
            for (Datacloud.MatchRecord thisMatchRecord : mr.getMatchRecords()) {
                System.debug('MA: Record: ' + thisMatchRecord.getRecord());
            }
        }
    }
}