Skip to content

Commit 31e6ff7

Browse files
authored
BAP-21801: Add upsert strategy for Batch API (#36157)
1 parent b90b069 commit 31e6ff7

File tree

8 files changed

+273
-7
lines changed

8 files changed

+273
-7
lines changed

api/batch-api.rst

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,36 @@ To mark records that should be updated, use the ``update`` meta property:
6060
See :ref:`Creating and Updating Related Resources with Primary API Resource <web-services-api--create-update-related-resources>`
6161
for more details about this meta property.
6262

63+
To mark records that should be updated when they exist in the database or created when they do not exist, use the ``upsert`` meta property:
64+
65+
.. code-block:: none
66+
67+
{
68+
"data": [
69+
{
70+
"meta": {
71+
"upsert": true
72+
},
73+
"type": "entityType",
74+
"id": 1,
75+
"attributes": {...},
76+
"relationships": {...}
77+
},
78+
{
79+
"meta": {
80+
"upsert": true
81+
},
82+
"type": "entityType",
83+
"id": 2,
84+
"attributes": {...},
85+
"relationships": {...}
86+
}
87+
]
88+
}
89+
90+
See :ref:`Creating Resource or Updating Existing Resource via Single API Request <web-services-api--upsert-operation>`
91+
for more details about this meta property.
92+
6393
Included Items
6494
--------------
6595

api/http-methods.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,10 @@ On successful creation, HTTP response code 201 is returned.
100100
It is possible to create both primary and related API resources via a single API request. For details, see the
101101
:ref:`Creating and Updating Related Resources with Primary API Resource <web-services-api--create-update-related-resources>` section.
102102

103+
.. note::
104+
For some resources, you can create a resource (if it did not already exist) or update it (if it does) via a single API request.
105+
For details, see the :ref:`Creating Resource or Updating Existing Resource via Single API Request <web-services-api--upsert-operation>` section.
106+
103107

104108
.. _web-services-api--http-methods--patch:
105109

@@ -120,6 +124,10 @@ server should be modified to produce a new version.
120124
.. note::
121125
For details, see the :ref:`Creating and Updating Related Resources with Primary API Resource <web-services-api--create-update-related-resources>` section.
122126

127+
.. note::
128+
For some resources, you can create a resource (if it did not already exist) or update it (if it does) via a single API request.
129+
For details, see the :ref:`Creating Resource or Updating Existing Resource via Single API Request <web-services-api--upsert-operation>` section.
130+
123131

124132
.. _web-services-api--http-methods--delete:
125133

api/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ Find more information about Web API in the following topics:
4848
resource-fields
4949
filters
5050
create-update-related-resources
51+
upsert-operation
5152
client-requirements
5253
batch-api
5354

api/upsert-operation.rst

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
.. _web-services-api--upsert-operation:
2+
3+
Creating Resource or Updating Existing Resource via Single API Request
4+
======================================================================
5+
6+
Some API resources can be created, if a particular resource does not exists, or updated, if it already exists,
7+
via a single API request. It is called an "upsert" operation and it works the following way:
8+
9+
1. If a resource is not found by a upsert criteria, then a new resource is created according to the request body
10+
and a 201 (Created) status code is returned.
11+
2. If a resource is found, then the resource is updated according to the request body
12+
and a 200 (Ok) status code is returned.
13+
3. If several resources are found, then the resource is not created or updated,
14+
and a 409 (Conflict) status code is returned.
15+
16+
The upsert criteria is specified in the |JSON:API: Meta Section| section using an "upsert" option. To match a resource
17+
by the resource identifier the "upsert" option should have ``true`` or ``["id"]`` value. To match a resource by other
18+
field(s), this (these) field(s) should be specified in the "upsert" option value, e.g. ``["field1", "field2"]``.
19+
20+
The upsert operation can be supported by POST and/or PATCH |JSON:API| requests. With the POST request,
21+
you can match a resource by the resource identifier or by some other field(s). With the PATCH request,
22+
you can match a resource by the resource identifier only.
23+
24+
The documentation of POST and PATCH requests in the :ref:`API Sandbox <web-services-api--sandbox>` contains
25+
information whether a resource supports the upsert operation. For example.:
26+
27+
.. image:: /img/backend/api/upsert_operation_note.png
28+
:alt: An example of the upsert operation note
29+
30+
An example of a POST upsert requests when a resource should be matched by the resource identifier:
31+
32+
**Request**
33+
34+
.. code-block:: http
35+
36+
POST /api/weightunits HTTP/1.1
37+
Content-Type: application/vnd.api+json
38+
Accept: application/vnd.api+json
39+
40+
**Request Body**
41+
42+
.. code-block:: json
43+
44+
{"data": {
45+
"type": "weightunits",
46+
"id": "kg",
47+
"meta": {
48+
"upsert": true
49+
},
50+
"attributes": {
51+
"conversionRates": {
52+
"lbs": 2.2
53+
}
54+
}
55+
}
56+
}
57+
58+
An example of a PATCH upsert requests when a resource should be matched by the resource identifier:
59+
60+
**Request**
61+
62+
.. code-block:: http
63+
64+
PATCH /api/weightunits/kg HTTP/1.1
65+
Content-Type: application/vnd.api+json
66+
Accept: application/vnd.api+json
67+
68+
**Request Body**
69+
70+
.. code-block:: json
71+
72+
{"data": {
73+
"type": "weightunits",
74+
"id": "kg",
75+
"meta": {
76+
"upsert": true
77+
},
78+
"attributes": {
79+
"conversionRates": {
80+
"lbs": 2.2
81+
}
82+
}
83+
}
84+
}
85+
86+
An example of a POST upsert request when a resource should be matched by some field:
87+
88+
**Request**
89+
90+
.. code-block:: http
91+
92+
POST /api/taxjurisdictions HTTP/1.1
93+
Content-Type: application/vnd.api+json
94+
Accept: application/vnd.api+json
95+
96+
**Request Body**
97+
98+
.. code-block:: json
99+
100+
{"data": {
101+
"type": "taxjurisdictions",
102+
"meta": {
103+
"upsert": ["code"]
104+
},
105+
"attributes": {
106+
"code": "SOME_TAX_JURISDICTION",
107+
"description": "Some tax jurisdiction description",
108+
"regionText": null,
109+
"zipCodes": [
110+
{"from": "90011", "to": null},
111+
{"from": "90201", "to": "90280"}
112+
]
113+
},
114+
"relationships": {
115+
"country": {
116+
"data": {
117+
"type": "countries",
118+
"id": "US"
119+
}
120+
},
121+
"region": {
122+
"data": {
123+
"type": "regions",
124+
"id": "US-CA"
125+
}
126+
}
127+
}
128+
}
129+
}
130+
131+
.. include:: /include/include-links-dev.rst
132+
:start-after: begin

backend/api/commands.rst

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ To work only with the specified |API documentation views| use the ``--view`` opt
4949
5050
php bin/console oro:api:doc:cache:clear --view=rest_json_api
5151
52+
.. _oroapidump-command:
53+
5254
oro:api:dump
5355
------------
5456

@@ -84,12 +86,24 @@ or
8486
8587
php bin/console oro:api:dump users --sub-resources
8688
87-
To get all entities that are not accessible via the API, see the ``--not-accessible`` option:
89+
To get all entities that are not accessible via the API, use the ``--not-accessible`` option:
8890

8991
.. code-block:: none
9092
9193
php bin/console oro:api:dump --not-accessible
9294
95+
To get all entities that support a specific API action, use the ``--action`` option:
96+
97+
.. code-block:: none
98+
99+
php bin/console oro:api:dump --action=update_list
100+
101+
To get all entities that support :ref:`the upsert operation <web-services-api--upsert-operation>`, use the ``--upsert`` option:
102+
103+
.. code-block:: none
104+
105+
php bin/console oro:api:dump --upsert
106+
93107
.. _oroapidebug:
94108

95109
oro:api:debug
@@ -170,6 +184,8 @@ The ``--request-type`` option can limit the scope to the specified request type(
170184
171185
php bin/console oro:api:debug --request-type=any other options and arguments
172186
187+
.. _oroapiconfigdump-command:
188+
173189
oro:api:config:dump
174190
-------------------
175191

@@ -223,6 +239,8 @@ You can pass multiple options:
223239
224240
php bin/console oro:api:config:dump users --extra=sorters --extra=descriptions --extra=filters --extra="Acme\Bundle\DemoBundle\Config\MyConfigExtra"
225241
242+
.. _oroapimetadatadump-command:
243+
226244
oro:api:metadata:dump
227245
---------------------
228246

@@ -258,6 +276,8 @@ To include the HATEOAS links to the metadata, use the ``--hateoas`` option:
258276
259277
php bin/console oro:api:metadata:dump --hateoas <entity>
260278
279+
.. _oroapiconfigdumpreference-command:
280+
261281
oro:api:config:dump-reference
262282
-----------------------------
263283

@@ -275,6 +295,8 @@ You can use the ``--max-nesting-level`` option to limit the depth of nesting tar
275295
276296
.. _web-api--commands--oro-cron-api-async_operations-cleanup:
277297

298+
.. _orocronapiasyncoperationscleanup-command:
299+
278300
oro:cron:api:async_operations:cleanup
279301
-------------------------------------
280302

@@ -291,4 +313,4 @@ To show the number of obsolete asynchronous operations without the deletion of t
291313
php bin/console oro:cron:api:async_operations:cleanup --dry-run
292314
293315
.. include:: /include/include-links-dev.rst
294-
:start-after: begin
316+
:start-after: begin

backend/api/configuration.rst

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,10 @@ The ``entities`` section describes the configuration of entities.
228228

229229
* **identifier\_field\_names** *string[]* - The names of identifier fields of the entity. Use this option to override names set in a configuration file (for the API resource not based on the ORM entity) or retrieve from entity metadata (for ORM entities). This option is helpful when you do not want to use the primary key as an entity identifier in the API.
230230

231+
* **identifier\_description** *string* - A human-readable description of the API resource identifier. Used in auto-generated documentation only.
232+
233+
* **upsert** *array* - The configuration of the upsert operation. For details, see :ref:`Configure Upsert Operation <configure-upsert-operation>`.
234+
231235
* **form\_type** *string* - The form type to use for the entity in the :ref:`create <create-action>` and :ref:`update <update-action>` actions. By default the ``Symfony\Component\Form\Extension\Core\Type\FormType`` form type is used.
232236

233237
* **form\_options** *array* - The form options to use for the entity in the :ref:`create <create-action>` and :ref:`update <update-action>` actions.
@@ -266,6 +270,8 @@ By default, the following form options are set:
266270
- { name: HINT_FORCE_PARTIAL_LOAD, value: false }
267271
- { name: HINT_CUSTOM_OUTPUT_WALKER, value: 'Acme\Bundle\DemoBundle\AST_Walker_Class'}
268272
excluded: false
273+
upsert:
274+
add: [ 'field1' ]
269275
form_type: Acme\Bundle\DemoBundle\Api\Form\Type\SomeEntityType
270276
form_options:
271277
validation_groups: ['Default', 'api', 'my_group']
@@ -617,7 +623,7 @@ Add an additional status code for the ``delete`` action:
617623
actions:
618624
delete:
619625
status_codes:
620-
'417': 'Returned when expectations failed'
626+
417: 'Returned when expectations failed'
621627
622628
or
623629

@@ -629,7 +635,7 @@ or
629635
actions:
630636
delete:
631637
status_codes:
632-
'417':
638+
417:
633639
description: 'Returned when expectations failed'
634640
635641
Remove the existing status code for the ``delete`` action:
@@ -642,7 +648,7 @@ Remove the existing status code for the ``delete`` action:
642648
actions:
643649
delete:
644650
status_codes:
645-
'417': false
651+
417: false
646652
647653
or
648654

@@ -654,7 +660,7 @@ or
654660
actions:
655661
delete:
656662
status_codes:
657-
'417':
663+
417:
658664
exclude: true
659665
660666
Exclude a field for the ``update`` action:

0 commit comments

Comments
 (0)