Connection.upsert for Inserting New Records Using Id as the External ID
See original GitHub issueI encountered an error METHOD_NOT_ALLOWED: HTTP Method 'PATCH' not allowed. Allowed are GET,HEAD,POST
when connection.sobject('Account').upsert({Name: 'foo'}, 'Id')
.
I found description below in developer guide. https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/dome_upsert.htm
Inserting New Records Using Id as the External ID This example uses the POST method as a special case to insert a record where the Id field is treated as the external ID. Because the value of Id is null, it’s omitted from the request. This pattern is useful when you’re writing code to upsert multiple records by different external IDs and you don’t want to request a separate resource. POST using Id is available in API version 37.0 and later.
So if external ID field is Id and Id is not present, HTTP method for upsert should be POST
.
These lines: https://github.com/jsforce/jsforce/blob/a99a38b55346388f53a47d8b2e5afcace43c232b/lib/connection.js#L754
var url = [ self._baseUrl(), "sobjects", sobjectType, extIdField, extId ].join('/');
return self.request({
method : 'PATCH',
url : url,
should be like:
var url = _.compact([ self._baseUrl(), "sobjects", sobjectType, extIdField, extId ]).join('/');
return self.request({
method : (extIdField.toUpperCase() === 'ID' && extId == null) ? 'POST' : 'PATCH',
url : url,
Issue Analytics
- State:
- Created 6 years ago
- Reactions:6
- Comments:8 (2 by maintainers)
Top GitHub Comments
@stomita Hi, this is the current use-case I am looking to use
upsert
for:In my api, I am making a request to update a master object in SalesForce, when this request is made, there may or may not exist a related detail object to this master object. I determine this by making a query to check for that detail object where the
Master-Detail
field is equal to the master objectId
, e.g.SELECT Id FROM DetailObject__c WHERE MasterDetailField__c = 'MasterObjectId';
If no records are returned I am creating that detail object, if records are returned than I know I can update the detail object.So instead of conditionally checking if there are records returned myself and either making a
create
orupdate
call, I wanted to useupsert
to do it for me, using @tarot 's suggested change, I was able to get this to work:Your payload is missing the external field as such the request URL is breaking - I submitted PR#931
In the mean time try adding a slash to the extIdField field so that it reads:
connection.sobject('Account').upsert({Name: 'foo'}, 'Id/')
or adding Id to your record (doesn’t work if Id is
null
or" "
unfortunately).connection.sobject('Account').upsert({Name: 'foo', Id:'123'}, 'Id/')