# Operations for Large Groups/Lists in FHIR
## `$add` operation
:::success
This instance-level operation merges array entries into an existing ("target") resource, based on values from a supplied ("input") resource, ignoring any values that are already present in the target.
:::
:::info
#### Example invocation: add two items to a Group
This example adds up to 2 new members to the member array of Group 123, based on whether these entity/period combinations already exist.
```json
POST /Group/123/$add
Content-Type: application/fhir+json
If-Match: W/"4"
{
"resourceType": "Group",
"type": "Person",
"actual": true,
"member": [{
"entity": {"reference": "Patient/123"},
"period": {"start": "2020-07-10"},
}, {
"entity": {"reference": "Patient/456"}
}]
}
```
#### Example invocation: add two items to a List
This example adds up to 2 entries to the entry array of List 123, based on whether these item/date combinations already exist.
```json
POST /List/123/$add
Content-Type: application/fhir+json
If-Match: W/"4"
{
"resourceType": "List",
"status": "current",
"mode": "working",
"entry": [{
"item": {"reference": "Patient/123"},
"date": "2020-01-05"
}, {
"item": {"reference": "Patient/456"}
}]
}
```
:::
### `$add` operation details
Instance-level operation, invoked by
* `POST /Group/123/$add` to grow `Group.member`
* `POST /List/123/$add` to grow `List.entry`
* (Other target resource types may be added in future, if use cases arise.)
Input Parameter:
* `additions`: an input resource matching the type of the target resource. The client SHALL populate all required top-level elements in a way that matches the target resource, to ensure the resource is technically valid. The server SHALL ignore all elements except for the relevant array (e.g., `Group.member` or `List.entry`).
Behavior:
* The server SHALL extend the target resource array with any entries from the input resource array that do not match an existing entry. See [Matching Algorithm](#Matching-Algorithm).
### Contention Management
Clients MAY supply an `If-Match` header with an ETag reflecting the current version of the target resource. Servers SHALL NOT proceed if a supplied ETag does not match the current version of the target resource, following the scheme described at https://hl7.org/fhir/http.html#concurrency.
## `$remove` operation
:::success
This instance-level operation removes array entries from an existing ("target") resource, based on a supplied ("input") resource, ignoring any values that are already absent in the target.
:::
:::info
#### Example invocation: remove two items to a Group
This example removes elements from the member array of Group 123 if they match the supplied combinations of entity/period.
```json
POST /Group/123/$remove
Content-Type: application/fhir+json
If-Match: W/"4"
{
"resourceType": "Group",
"type": "Person",
"actual": true,
"member": [{
"entity": {"reference": "Patient/123"},
"period": {"start": "2020-07-10"},
}, {
"entity": {"reference": "Patient/456"},
}]
}
```
#### Example invocation: add two items to a List
This example removes elements from the entry array of List 123 if they match the supplied combinations of item/date.
```json
POST /List/123/$remove
Content-Type: application/fhir+json
If-Match: W/"4"
{
"resourceType": "List",
"status": "current",
"mode": "working",
"entry": [{
"item": {"reference": "Patient/123"},
}, {
"item": {"reference": "Patient/456"},
"date": "2020-01-12"
}]
}
```
:::
### `$remove` operation details
Instance-level operation, invoked by
* `POST /Group/123/$remove` to shrink `Group.member`
* `POST /List/123/$remove` to shrink `List.entry`
* (Other target resource types may be added in future, if use cases arise.)
Input Parameter:
* `removals`: an input resource matching the type of the target resource. The client SHALL populate all required top-level elements in a way that matches the target resource, to ensure the resource is technically valid. The server SHALL ignore all elements except for the relevant array (e.g., `Group.member` or `List.entry`).
Behavior:
* The server SHALL remove any entries in the target resource's array that match an entry in the input resource's array. See [Matching Algorithm](#Matching-Algorithm).
### Contention Management
Clients MAY supply an `If-Match` header with an ETag reflecting the current version of the target resource. Servers SHALL NOT proceed if a supplied ETag does not match the current version of the target resource, following the scheme described at https://hl7.org/fhir/http.html#concurrency.
## `$filter` operation
:::success
This instance-level operation returns the subset of array entries from an existing ("target") resource that match values from a supplied ("input") resource.
:::
:::info
#### Example invocation: filter a List by Patient
This example filters List 123 to return items referencing Patient 456 (on any day) Patient 789 (in July 2022.
```json
POST /List/123/$filter
Content-Type: application/fhir+json
{
"resourceType": "List",
"status": "current",
"mode": "working",
"entry": [{
"item": {"reference": "Patient/456"},
}, {
"item": {"reference": "Patient/789"},
"date": "2022-07"
}]
}
```
If this list included two items (with any date) referencing Patient 456, and one item with a date in July 2022 referencing Patient 789, then three subsetted entries would be returned:
```json
{
"resourceType": "List",
"id": "123",
"meta": {
"tag": [{
"system": "http://terminology.hl7.org/CodeSystem/v3-ObservationValue",
"code": "SUBSETTED"
}]
},
"status": "current",
"mode": "working",
"title": "Patient waiting list",
"entry": [{
"date": "2022-07-01",
"flag": {"text": "Registered"},
"item": {"reference": "Patient/456/_history/1"}
}, {
"date": "2022-07-02T11:00:00Z",
"flag": {"text": "Escalated"},
"item": {"reference": "Patient/456/_history/2"}
}, {
"date": "2022-07-02T12:00:00Z",
"flag": {"text": "Escalated"},
"item": {"reference": "Patient/789"}
}]
}
```
:::
### `$filter` operation details
Instance-level operation, invoked by
* `POST /Group/123/$filter` to return a filtered subset of `Group.member`
* `POST /List/123/$filter` to return a filtered subset of `List.entry`
* (Other target resource types may be added in future, if use cases arise.)
Input Parameter:
* `probes`: an input resource matching the type of the target resource. The client SHALL populate all required top-level elements in a way that matches the target resource, to ensure the resource is technically valid. The server SHALL ignore all elements except for the relevant array (e.g., `Group.member` or `List.entry`).
Behavior:
* The server SHALL determine which existing array entries in the target resource "match" each entry in the input resource. See [Matching Algorithm](#Matching-Algorithm).
* The server SHALL return a resource that includes all matching array entries
* The returned resource SHALL include a `SUBSETTED` Coding in `.meta.tag`
---
:::success
### Matching Algorithm
Applies to: `$add`, `$remove`, and `$filter`.
This algorithm determines whether an entry in the target resource array "matches" an entry in the input resource array. An entry is considered to "match" if:
* each supplied element in the input entry is present in the target entry AND
* each supplied element has a value in the target entry that is:
* identical to the value in the input entry OR
* more specific than the value in the input entry
* a date is "more specific" if it covers a narrower timespan, e.g. an input value of "2022-07" would match a target value of "2022-07-01"
* a reference is "more specific" if it points to a historical version, e.g. an input value of "Patient/123" would match a target value of "Patient/123/_history/456"
---
##### Example 1: a single probe
Entry in input resource:
```json
{
"item": {"reference": "Patient/123"}
}
```
Entry in target resource:
```json
{
"date": "2022-07-01",
"item": {"reference": "Patient/123/_history/2"}
}
```
Result: this is a **match**, because the target entry contains a matching element for the input entry's elements (`item` and `item.reference`). The presence of an additional `date` element in the target resource does not affect the result.
---
##### Example 2: asymmetry
Now consider the same inputs from Example (1), but swap their roles (input / target) as follows.
Entry in input resource:
```json
{
"date": "2022-07-01",
"item": {"reference": "Patient/123/_history/2"}
}
```
Entry in target resource:
```json
{
"item": {"reference": "Patient/123"}
}
```
Result: this is **not a match**, because the target entry contains no match for the input entry's `date` element, and also no match for the input entry's version-specific `item.reference` element. This example shows that the comparision operation is not symmetric; inputs match more-specific targets, not less-specific targets.
:::