# Array Operations API

> Push, add to set, pull, pull all, pop and set elements of array fields in MongoDB documents with the array operations API of API Maker, several operations in one call.

Source: https://docs.apimaker.dev/v4/docs/apis-all/schema-apis/auto-generated-schema-based-array-operations-api.html

Changes array fields of MongoDB documents in place : push, addToSet, pull, pullAll, pop and set, on every document matching `find`, several operations in one call.

| | |
|---|---|
| Method | PUT |
| URL | `/api/schema/admin/mysql8/inventory/customers/array-operations` |
| Body | `{ find, select?, operations: [ … ] }` |
| Query params | none |
| Answer | `data` : one array per operation with the documents matched, projected to the array (or `select`) |
| Databases | MongoDB only |
| Cached | no (a write ; it resets the cache of the table) |
| From code | [`g.sys.db.arrayOperations`](https://docs.apimaker.dev/v4/examples/sys/db/arrayOperations.html) |
| API id | `SCHEMA_ARRAY_OPERATIONS` (groups, settings, hooks, WebSocket subscriptions) |
| Without a schema | `/api/gen/admin/mysql8/inventory/customers/array-operations` : [below](https://docs.apimaker.dev/v4/docs/apis-all/schema-apis/auto-generated-schema-based-array-operations-api.html#without-a-schema) |

> **Generated (`/api/gen`) or schema (`/api/schema`) ?**
>
> Both families offer the same operations on the same URL pattern. The **schema APIs** read the [schema](https://docs.apimaker.dev/v4/docs/schema/schema.html) of the table : values are converted to their types, validated, encrypted, defaulted and numbered before they reach the database. The **generated APIs** are schemaless : they pass your data as it is, so a number sent as `"22"` stays a string. Use the schema APIs for the tables your application writes to, and the generated APIs for quick reads and for tables without a schema.

## The URL

`/api/schema/admin/mysql8/inventory/customers/array-operations` : replace `admin` with the user path of your account, `mongodb` with your instance, `inventory` with the database and `customers` with the table. The examples use this table :

| customer_id | first_name | last_name | last_update           | pincode | isActive |
|-------------|------------|-----------|-----------------------|---------|----------|
| 1           | Bob        | lin       | 2022-11-14 04: 34: 58 | 382345  | 1        |
| 2           | Alice      | Page      | 2022-10-15 02: 10: 40 | 382346  | 1        |
| 3           | Mallory    | Brown     | 2022-09-13 03: 44: 05 | 382347  | 1        |
| 4           | Eve        | Mathly    | 2022-11-12 01: 59: 33 | 382348  | 1        |
| 5           | Eve        | Page      | 2022-11-12 01: 59: 33 | 382349  | 1        |

## The body

```json
{
    "find": { "customer_id": 1 },
    "operations": [
        { "operation": "push", "path": "ages", "dataToPush": [ { "age": 33, "birth_year": 1989 } ] }
    ]
}
```

| Key | Meaning |
|---|---|
| `find` | Which documents to change. `{}` : all of them. |
| `select` | The fields to return for the matched documents. Without it, the array of `path`. |
| `operations` | Run one after the other, each on every matched document. |

| Operation | Keys | Does |
|---|---|---|
| `push` | `path`, `dataToPush` (array), `position`, `slice`, `sort` | Appends the items. `position` inserts at an index, `slice` keeps the first N (or last N when negative), `sort` (`{ field: 1 or -1 }`) reorders. |
| `addToSet` | `path`, `dataToPush` (one value or an array) | Appends only the values which are not there yet. |
| `pull` | `path`, `queryToRemove` | Removes every item matching the query. |
| `pullAll` | `path`, `dataToPull` (array) | Removes every item equal to one of the values. |
| `pop` | `path`, `direction` | `1` removes the last item, `-1` the first. |
| `set` | `dataToSet`, `arrayFilters`, `upsert` | Updates fields of items with the positional `$[item]` syntax and its filters. |

## Push and pull

**Push two items at the front, keep the array at 10**

```json
{ "find": {}, "operations": [ { "operation": "push", "path": "ages", "dataToPush": [ { "age": 2 }, { "age": 5 } ], "position": 0, "slice": 10, "sort": { "age": 1 } } ] }
```

**Remove the items of a year**

```json
{ "find": { "customer_id": 1 }, "operations": [ { "operation": "pull", "path": "ages", "queryToRemove": { "birth_year": 1989 } } ] }
```

**Remove exact values**

```json
{ "find": {}, "operations": [ { "operation": "pullAll", "path": "tags", "dataToPull": [ "old", "draft" ] } ] }
```

## Set inside an array

```json
{
    "find": {},
    "operations": [ {
        "operation": "set",
        "dataToSet": { "ages.$[item].age": 45, "ages.$[item].birth_year": 1999 },
        "arrayFilters": [ { "item.birth_year": 1999 } ],
        "upsert": true
    } ]
}
```

- `arrayFilters` decide which items `$[item]` means, `upsert: true` inserts a document when `find` matches none.

## Several operations at once

```json
{ "find": {}, "operations": [
    { "operation": "push", "path": "ages", "dataToPush": [ { "age": 60 } ] },
    { "operation": "pull", "path": "ages", "queryToRemove": { "age": 2 } }
] }
```

**Answer : one entry per operation**

```json
{ "success": true, "statusCode": 200, "data": [
    [ { "_id": "63e0775abd0e063920533f7c", "ages": [ { "age": 33 }, { "age": 60 } ] } ],
    [ { "_id": "63e0775abd0e063920533f7c", "ages": [ { "age": 33 }, { "age": 60 } ] } ]
] }
```

## With a schema

- The items pushed, added or set are converted and validated against the schema of the array field before they are written, like a save. Encrypted fields inside an array are handled too.

## From your code

[`g.sys.db.arrayOperations`](https://docs.apimaker.dev/v4/examples/sys/db/arrayOperations.html) makes the same call from custom APIs, hooks, events, schedulers and test cases, with the same headers and params. To get the whole [response envelope](https://docs.apimaker.dev/v4/docs/apis-all/response-format.html) instead of `data`, pass `true` as the second argument in TypeScript, or call it through `g.sys.db.full` in the other languages.

## Without a schema : /api/gen

Every table also answers this operation under `/api/gen`, with or without a schema :

| | |
|---|---|
| URL | `/api/gen/admin/mysql8/inventory/customers/array-operations` |
| API id | `GEN_ARRAY_OPERATIONS` (groups, settings, hooks, WebSocket subscriptions) |
| From code | [`g.sys.db.gen.arrayOperationsGen`](https://docs.apimaker.dev/v4/examples/sys/db/arrayOperations.html#without-a-schema) |

The data passes as it is : nothing is converted, validated, defaulted, encrypted or numbered, and a filter matches the type you send (`"22"` does not match the number `22`). On MongoDB, strings which look like ObjectIds are converted. The query params, headers and errors are the ones of this page.

## Headers

Every call takes the [request headers](https://docs.apimaker.dev/v4/docs/apis-all/header/requestHeader.html) : the tokens, `x-am-response-case`, `x-am-content-type-response` (JSON, XML, YAML…), `x-am-response-object-type: make_flat`, `x-am-cache-control`, `x-am-get-encrypted-data`, `x-am-internationalization`, `x-am-tenant-username`, `x-am-meta`.

## Errors

| Code | When |
|---|---|
| `401` | The token in `x-am-authorization` is missing or invalid. |
| `403` | No group of the API user grants this API of this table, or a field of the request. |
| `404` | The instance, database or table of the URL does not exist, or the table has no schema (use `/api/gen`). |
| `400` | The query or the body is wrong : the [error messages](https://docs.apimaker.dev/v4/docs/apis-all/error-codes.html) say which key and why. |

## Related

- [All APIs at a glance](https://docs.apimaker.dev/v4/docs/apis-all/overview.html) · [Query params](https://docs.apimaker.dev/v4/docs/apis-all/query-params/query-params.html) · [Response format](https://docs.apimaker.dev/v4/docs/apis-all/response-format.html) · [Pre hooks](https://docs.apimaker.dev/v4/docs/apis-all/hooks/preHook-api.html) and [post hooks](https://docs.apimaker.dev/v4/docs/apis-all/hooks/postHook-api.html) · [Automatic caching](https://docs.apimaker.dev/v4/docs/features/automatic-caching.html)
- [Table schema](https://docs.apimaker.dev/v4/docs/schema/schema.html) : what the conversions and validations do to every write.
