What does it mean "master" records and what is "slave"?
Question.
The documentation says that in order to select only child records of one object related to the previously selected parent records of another object, I need to set master=false for the child object (since default is master=true). So the child object becomes "slave".
I do not completely understand how exactly does it work, can you provide more detailed information?
And another question, can I define multiple "master" objects and what can be an impact of this?
Answer.
As the answer on your first question, how does it work, we can provide some brief information about master/slave modes.
You should consider these points when creating your export.json:
- By default all sObjects are in master mode.
- The Plugin always executes query string on master object AS IS it's defined in the export.json. So all limiting clauses like WHERE or LIMIT are included and reduce the final amount of selected records.
- For slave object the Plugin removes LIMIT but keeps WHERE statements, then it adds extra condition to select only the child records.
Let's see the example below.
For the following simplest export.json configuration with only one master object:
{
"objects": [
{
"query" : "SELECT Id FROM Account LIMIT 10",
"externalId": "Name",
"operation": "Upsert"
},
{
"query" : "SELECT Id, AccountId FROM Contact WHERE FirstName = 'John' LIMIT 100",
"externalId": "LastName",
"operation": "Upsert",
"master": false
}
]
}
... the Plugin will execute the following queries:
For the Account object:
SELECT Id, Name FROM Account LIMIT 10
The query of Account is executed AS IS without modification.
For the Contact object:
SELECT Id, LastName, AccountId, Account.Name FROM Contact WHERE (FirstName = 'John') AND (AccountId IN ('001XXXXXXXXXXXX', '001XXXXXXXXXXXX', ..... ))
The Contact records are filtered by ids of the previously selected account records, since they are slave records.
The Plugin keeps the original WHERE clause and removes LIMIT.
The answer on your second question is: yes, of course, you can define multiple master objects.
For the following configuration with Account and Language__c as master objects:
{
"objects": [
{
"query" : "SELECT Id, Language__c FROM Account LIMIT 10",
"externalId": "Name",
"operation": "Upsert"
},
{
"query" : "SELECT Id, AccountId FROM Contact WHERE FirstName = 'John' LIMIT 100",
"externalId": "LastName",
"operation": "Upsert",
"master": false
},
{
"query" : "SELECT Id, Name FROM Language__c WHERE Region__c == 'EU' LIMIT 5",
"externalId": "Code__c",
"operation": "Readonly"
}
]
}
... the queries are as following:
For the Language__c object:
SELECT Id, Language__c FROM Account LIMIT 10
Language records are fetched as it's has been set in the query statement (only 10 records are fetched)
For the Account object:
SELECT Id, Name, Language__c, Language__r.Code__c FROM Account LIMIT 10
The Account records are NOT filtered by the Languages , instead they are fetched AS IS, since Account is also a master object.
For the Contact object:
SELECT Id, LastName, AccountId, Account.Name FROM Contact WHERE (FirstName = 'John') AND (AccountId IN ('001XXXXXXXXXXXX', '001XXXXXXXXXXXX', ..... ))
The Contact records are filtered by ids of the previously selected account records, since they are slave records.
The Plugin keeps the original WHERE clause and removes LIMIT.
Notes:
The consequences of setting multiple master records could be the the Tool might not found overlapped records between two master objects. In our example, it can be a situation when none of the 10 selected Accounts will have parent 'EU' Languages and you will run into the 'Missing lookup records' issue for the Account object.
But in some situations when you know which records will be retrieved by your query and you need to transfer only that records, setting multiple master objects could be a very good approach to transfer very limited subset of records.
Setting master=false will allow the SFDMU to locate automatically related records which will reduce a risk of missing parent records issue.
But if you want to add WHERE clause to a slave object, you have to do that carefully, because the Tool will still use your WHERE statement to initially limit the amount of fetched records (before requesting only related records).