From 9ae0959f662287c8f1c0cc27a008a707d17591c5 Mon Sep 17 00:00:00 2001 From: adityaoberai Date: Tue, 28 Oct 2025 02:51:53 +0530 Subject: [PATCH 01/13] Add db operators docs --- .../docs/products/databases/+layout.svelte | 5 + .../databases/db-operators/+page.markdoc | 151 ++++++++++++++++++ 2 files changed, 156 insertions(+) create mode 100644 src/routes/docs/products/databases/db-operators/+page.markdoc diff --git a/src/routes/docs/products/databases/+layout.svelte b/src/routes/docs/products/databases/+layout.svelte index da40baa0e5..09b06b7817 100644 --- a/src/routes/docs/products/databases/+layout.svelte +++ b/src/routes/docs/products/databases/+layout.svelte @@ -105,6 +105,11 @@ label: 'CSV imports', href: '/docs/products/databases/csv-imports', new: isNewUntil('31 Jul 2025') + }, + { + label: 'Database operators', + href: '/docs/products/databases/db-operators', + new: isNewUntil('31 Dec 2025') } ] }, diff --git a/src/routes/docs/products/databases/db-operators/+page.markdoc b/src/routes/docs/products/databases/db-operators/+page.markdoc new file mode 100644 index 0000000000..f76086c1f9 --- /dev/null +++ b/src/routes/docs/products/databases/db-operators/+page.markdoc @@ -0,0 +1,151 @@ +--- +layout: article +title: Database operators +description: Update multiple fields atomically without fetching the full row. Perform numeric, array, string, and date updates in a single, consistent workflow. +--- + +Database operators let you update fields directly on the server without fetching the full row. Instead of sending new values, you describe the action you want: increment, append, replace, or adjust. This eliminates race conditions and reduces bandwidth usage when updating any values that need to be modified atomically. The operation is applied atomically at the storage layer for safe, concurrent updates. + +- Atomic by field: Each operation is applied safely at the storage layer to prevent lost updates under concurrency. +- Multi-field updates: Apply multiple operations across different fields in a single request or transaction. +- Type-safe: Operators are exposed through typed SDK methods for clarity and safety. +- Transaction-ready: Operators can be staged and committed alongside other database actions for consistent writes. + +# How database operators work {% #how-database-operators-work %} + +Instead of the traditional **read-modify-write** pattern, database operators use dedicated methods to modify values directly on the server. The server applies the change atomically under concurrency control and returns the new value. + +Let's take an example of appending a value to an array field. + +**Traditional approach:** +1. Fetch row → `{ letters: ['a', 'b' ] }` +2. Update client-side → `letters: ['a', 'b', 'c']` +3. Write back → `{ letters: ['a', 'b', 'c'] }` + +**Atomic approach:** +1. Call `createOperations()` with the column name and the value to append +2. Server applies atomically → `letters: ['a', 'b', 'c']` + +Here's how you can do so programmatically: + +{% multicode %} +```js +import { Client, Databases } from "appwrite"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') + .setProject(''); + +const databases = new Databases(client); + +const result = await databases.createOperations({ + transactionId: '', + operations: [ + { + "action": "arrayAppend", + "databaseId": "", + "tableId": "", + "rowId": "", + "data": { + "letters": ['a', 'b', 'c'] + } // This field is optional, depending on the operator + } + ] +}); +``` + +```dart +import 'package:dart_appwrite/dart_appwrite.dart'; + +Client client = Client() + .setEndpoint('https://.cloud.appwrite.io/v1') + .setProject(''); + +Databases databases = Databases(client); + +Transaction result = await databases.createOperations( + transactionId: '', + operations: [ + { + "action": "arrayAppend", + "databaseId": "", + "tableId": "", + "rowId": "", + "data": { + "letters": ['a', 'b', 'c'] + } // This field is optional, depending on the operator + } + ], +); +``` +{% /multicode %} + +{% info title="Why add a transaction ID?" %} + +Including a transaction ID allows you to group multiple operations into a single atomic transaction. This means either all operations succeed, or none are applied, ensuring data consistency. + +{% /info %} + +# When to use database operators {% #when-to-use %} + +Use operators when you need to: + +- Update fields frequently under concurrency (likes, scores, credits, inventory) +- Edit lists/tags without rewriting whole arrays +- Make small text changes in-place +- Adjust dates for lifecycle events or scheduling + +This keeps payloads small, avoids race conditions, and reduces round-trips. + +# Operator categories {% #operators %} + +The following operator types are available in v1. Choose the operator that matches your field type and intent. + +## Numeric operators {% #numeric %} + +Perform arithmetic on numeric fields without reading the row first. + +| Name | Purpose | +|------|---------| +| `increment` | Increases a numeric field by a specified value | +| `decrement` | Decreases a numeric field by a specified value | +| `multiply` | Multiplies a numeric field by a specified value | +| `divide` | Divides a numeric field by a specified value | +| `modulo` | Returns the remainder of a numeric field divided by a specified value | + + +## Array operators {% #array %} + +Edit lists in place: append, remove, or modify array items atomically. + +| Name | Purpose | +|------|---------| +| `arrayAppend` | Adds one or more elements to the end of an array | +| `arrayPrepend` | Adds one or more elements to the beginning of an array | +| `arrayInsert` | Inserts one or more elements at a specific position in an array | +| `arrayRemove` | Removes specified elements from an array | +| `arrayUnique` | Removes duplicate elements from an array | +| `arrayIntersect` | Returns only elements that exist in both arrays | +| `arrayDiff` | Returns elements that exist in the first array but not in the second | +| `arrayFilter` | Filters array elements based on specified criteria | + + +## String operators {% #string %} + +Make lightweight text changes without rewriting the whole row. + +| Name | Purpose | +|------|---------| +| `stringConcat` | Appends a string to the end of an existing string field | +| `stringReplace` | Replaces occurrences of a substring with a new string | + + +## Date operators {% #date %} + +Adjust time-based fields for lifecycle and scheduling logic. + +| Name | Purpose | +|------|---------| +| `dateAddDays` | Adds a specified number of days to a date field | +| `dateSubDays` | Subtracts a specified number of days from a date field | +| `dateSetNo` | Sets a date field to a specific value | From 9ae5f2e3748607d9e6dd2cb6cbfd5311e79b08ac Mon Sep 17 00:00:00 2001 From: Aditya Oberai Date: Wed, 29 Oct 2025 00:23:19 +0530 Subject: [PATCH 02/13] Update src/routes/docs/products/databases/db-operators/+page.markdoc --- src/routes/docs/products/databases/db-operators/+page.markdoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/routes/docs/products/databases/db-operators/+page.markdoc b/src/routes/docs/products/databases/db-operators/+page.markdoc index f76086c1f9..1c825e58e0 100644 --- a/src/routes/docs/products/databases/db-operators/+page.markdoc +++ b/src/routes/docs/products/databases/db-operators/+page.markdoc @@ -148,4 +148,4 @@ Adjust time-based fields for lifecycle and scheduling logic. |------|---------| | `dateAddDays` | Adds a specified number of days to a date field | | `dateSubDays` | Subtracts a specified number of days from a date field | -| `dateSetNo` | Sets a date field to a specific value | +| `dateSetNow` | Sets a date field to a specific value | From cfb5741ce34675b701fa044ed53f144207687555 Mon Sep 17 00:00:00 2001 From: Aditya Oberai Date: Wed, 29 Oct 2025 00:24:01 +0530 Subject: [PATCH 03/13] Update src/routes/docs/products/databases/db-operators/+page.markdoc --- .../docs/products/databases/db-operators/+page.markdoc | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/routes/docs/products/databases/db-operators/+page.markdoc b/src/routes/docs/products/databases/db-operators/+page.markdoc index 1c825e58e0..371f816180 100644 --- a/src/routes/docs/products/databases/db-operators/+page.markdoc +++ b/src/routes/docs/products/databases/db-operators/+page.markdoc @@ -80,11 +80,6 @@ Transaction result = await databases.createOperations( ``` {% /multicode %} -{% info title="Why add a transaction ID?" %} - -Including a transaction ID allows you to group multiple operations into a single atomic transaction. This means either all operations succeed, or none are applied, ensuring data consistency. - -{% /info %} # When to use database operators {% #when-to-use %} From 1ca50b847cccf40b678eb83f4cf049249931d86a Mon Sep 17 00:00:00 2001 From: Aditya Oberai Date: Thu, 30 Oct 2025 18:57:54 +0530 Subject: [PATCH 04/13] Update src/routes/docs/products/databases/db-operators/+page.markdoc --- src/routes/docs/products/databases/db-operators/+page.markdoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/routes/docs/products/databases/db-operators/+page.markdoc b/src/routes/docs/products/databases/db-operators/+page.markdoc index 371f816180..2799c5bb47 100644 --- a/src/routes/docs/products/databases/db-operators/+page.markdoc +++ b/src/routes/docs/products/databases/db-operators/+page.markdoc @@ -94,7 +94,7 @@ This keeps payloads small, avoids race conditions, and reduces round-trips. # Operator categories {% #operators %} -The following operator types are available in v1. Choose the operator that matches your field type and intent. +The following operators are currently available to use, based on field type and intent. ## Numeric operators {% #numeric %} From a1151cd6d66453d4ab82edff83b6a9ee090af32b Mon Sep 17 00:00:00 2001 From: Aditya Oberai Date: Thu, 30 Oct 2025 18:59:45 +0530 Subject: [PATCH 05/13] Update src/routes/docs/products/databases/db-operators/+page.markdoc --- .../databases/db-operators/+page.markdoc | 20 +++++++------------ 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/src/routes/docs/products/databases/db-operators/+page.markdoc b/src/routes/docs/products/databases/db-operators/+page.markdoc index 2799c5bb47..2acf8c4130 100644 --- a/src/routes/docs/products/databases/db-operators/+page.markdoc +++ b/src/routes/docs/products/databases/db-operators/+page.markdoc @@ -38,19 +38,13 @@ const client = new Client() const databases = new Databases(client); -const result = await databases.createOperations({ - transactionId: '', - operations: [ - { - "action": "arrayAppend", - "databaseId": "", - "tableId": "", - "rowId": "", - "data": { - "letters": ['a', 'b', 'c'] - } // This field is optional, depending on the operator - } - ] +const result = await tablesDB.updateRow({ + databaseId: "", + tableId: "", + rowId: "", + data: { + letters: Operator.arrayAppend(['c']) + } }); ``` From 86ac9353c13ecee76041679ba66174d6dbb1e961 Mon Sep 17 00:00:00 2001 From: Aditya Oberai Date: Mon, 3 Nov 2025 21:00:51 +0530 Subject: [PATCH 06/13] Apply suggestion from @adityaoberai --- src/routes/docs/products/databases/db-operators/+page.markdoc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/routes/docs/products/databases/db-operators/+page.markdoc b/src/routes/docs/products/databases/db-operators/+page.markdoc index 2acf8c4130..e6199bdbf3 100644 --- a/src/routes/docs/products/databases/db-operators/+page.markdoc +++ b/src/routes/docs/products/databases/db-operators/+page.markdoc @@ -30,13 +30,13 @@ Here's how you can do so programmatically: {% multicode %} ```js -import { Client, Databases } from "appwrite"; +import { Client, TablesDB } from "appwrite"; const client = new Client() .setEndpoint('https://.cloud.appwrite.io/v1') .setProject(''); -const databases = new Databases(client); +const tablesDB = new TablesDB(client); const result = await tablesDB.updateRow({ databaseId: "", From afacdd38e9e7b33b8c778bc9c4341ceeb8d603e3 Mon Sep 17 00:00:00 2001 From: Aditya Oberai Date: Mon, 3 Nov 2025 21:02:02 +0530 Subject: [PATCH 07/13] Apply suggestion from @adityaoberai --- src/routes/docs/products/databases/db-operators/+page.markdoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/routes/docs/products/databases/db-operators/+page.markdoc b/src/routes/docs/products/databases/db-operators/+page.markdoc index e6199bdbf3..a2ff7fb788 100644 --- a/src/routes/docs/products/databases/db-operators/+page.markdoc +++ b/src/routes/docs/products/databases/db-operators/+page.markdoc @@ -23,7 +23,7 @@ Let's take an example of appending a value to an array field. 3. Write back → `{ letters: ['a', 'b', 'c'] }` **Atomic approach:** -1. Call `createOperations()` with the column name and the value to append +1. Update/upsert the row with the appropriate value to append 2. Server applies atomically → `letters: ['a', 'b', 'c']` Here's how you can do so programmatically: From afe977d331739facf9b2be946012ea0450c955cb Mon Sep 17 00:00:00 2001 From: Aditya Oberai Date: Mon, 3 Nov 2025 16:32:20 +0000 Subject: [PATCH 08/13] Update examples + refactor operators list --- .../databases/db-operators/+page.markdoc | 315 +++++++++++++++--- 1 file changed, 270 insertions(+), 45 deletions(-) diff --git a/src/routes/docs/products/databases/db-operators/+page.markdoc b/src/routes/docs/products/databases/db-operators/+page.markdoc index a2ff7fb788..818fab06b7 100644 --- a/src/routes/docs/products/databases/db-operators/+page.markdoc +++ b/src/routes/docs/products/databases/db-operators/+page.markdoc @@ -22,7 +22,7 @@ Let's take an example of appending a value to an array field. 2. Update client-side → `letters: ['a', 'b', 'c']` 3. Write back → `{ letters: ['a', 'b', 'c'] }` -**Atomic approach:** +**Operator approach:** 1. Update/upsert the row with the appropriate value to append 2. Server applies atomically → `letters: ['a', 'b', 'c']` @@ -30,7 +30,7 @@ Here's how you can do so programmatically: {% multicode %} ```js -import { Client, TablesDB } from "appwrite"; +import { Client, TablesDB, Operator } from "appwrite"; const client = new Client() .setEndpoint('https://.cloud.appwrite.io/v1') @@ -51,25 +51,19 @@ const result = await tablesDB.updateRow({ ```dart import 'package:dart_appwrite/dart_appwrite.dart'; -Client client = Client() +final client = Client() .setEndpoint('https://.cloud.appwrite.io/v1') .setProject(''); -Databases databases = Databases(client); - -Transaction result = await databases.createOperations( - transactionId: '', - operations: [ - { - "action": "arrayAppend", - "databaseId": "", - "tableId": "", - "rowId": "", - "data": { - "letters": ['a', 'b', 'c'] - } // This field is optional, depending on the operator - } - ], +final tablesDB = TablesDB(client); + +final result = await tablesDB.updateRow( + databaseId: '', + tableId: '', + rowId: '', + data: { + 'letters': Operator.arrayAppend(['c']), + }, ); ``` {% /multicode %} @@ -88,53 +82,284 @@ This keeps payloads small, avoids race conditions, and reduces round-trips. # Operator categories {% #operators %} -The following operators are currently available to use, based on field type and intent. +The following operators are available, grouped by field type. Each operator updates the given column atomically on the server. ## Numeric operators {% #numeric %} Perform arithmetic on numeric fields without reading the row first. -| Name | Purpose | -|------|---------| -| `increment` | Increases a numeric field by a specified value | -| `decrement` | Decreases a numeric field by a specified value | -| `multiply` | Multiplies a numeric field by a specified value | -| `divide` | Divides a numeric field by a specified value | -| `modulo` | Returns the remainder of a numeric field divided by a specified value | +### increment {% #increment %} + +Increase a numeric field by a specified value. Optionally cap the result at a maximum value. + +{% multicode %} +```js +Operator.increment(1) +``` +```dart +Operator.increment(1) +``` +{% /multicode %} + +### decrement {% #decrement %} + +Decrease a numeric field by a specified value. Optionally cap the result at a minimum value. + +{% multicode %} +```js +Operator.decrement(1) +``` +```dart +Operator.decrement(1) +``` +{% /multicode %} + +### multiply {% #multiply %} + +Multiply a numeric field by a specified factor. Optionally cap the result at a maximum value. + +{% multicode %} +```js +Operator.multiply(2) +``` +```dart +Operator.multiply(2) +``` +{% /multicode %} + +### divide {% #divide %} + +Divide a numeric field by a specified divisor. Optionally cap the result at a minimum value. Divisor cannot be zero. + +{% multicode %} +```js +Operator.divide(5) +``` +```dart +Operator.divide(5) +``` +{% /multicode %} + +### modulo {% #modulo %} + +Set a numeric field to the remainder of itself divided by a specified value. + +{% multicode %} +```js +Operator.modulo(3) +``` +```dart +Operator.modulo(3) +``` +{% /multicode %} + +### power {% #power %} +Raise a numeric field to a specified exponent. Optionally cap the result at a maximum value. + +{% multicode %} +```js +Operator.power(2) +``` +```dart +Operator.power(2) +``` +{% /multicode %} ## Array operators {% #array %} Edit lists in place: append, remove, or modify array items atomically. -| Name | Purpose | -|------|---------| -| `arrayAppend` | Adds one or more elements to the end of an array | -| `arrayPrepend` | Adds one or more elements to the beginning of an array | -| `arrayInsert` | Inserts one or more elements at a specific position in an array | -| `arrayRemove` | Removes specified elements from an array | -| `arrayUnique` | Removes duplicate elements from an array | -| `arrayIntersect` | Returns only elements that exist in both arrays | -| `arrayDiff` | Returns elements that exist in the first array but not in the second | -| `arrayFilter` | Filters array elements based on specified criteria | +### arrayAppend {% #array-append %} + +Add one or more elements to the end of an array. + +{% multicode %} +```js +Operator.arrayAppend(['c']) +``` +```dart +Operator.arrayAppend(['c']) +``` +{% /multicode %} + +### arrayPrepend {% #array-prepend %} + +Add one or more elements to the beginning of an array. + +{% multicode %} +```js +Operator.arrayPrepend(['z']) +``` +```dart +Operator.arrayPrepend(['z']) +``` +{% /multicode %} + +### arrayInsert {% #array-insert %} + +Insert an element at a specific index in an array. + +{% multicode %} +```js +Operator.arrayInsert(1, 'x') +``` +```dart +Operator.arrayInsert(1, 'x') +``` +{% /multicode %} + +### arrayRemove {% #array-remove %} + +Remove a specified element from an array. + +{% multicode %} +```js +Operator.arrayRemove('b') +``` +```dart +Operator.arrayRemove('b') +``` +{% /multicode %} + +### arrayUnique {% #array-unique %} + +Remove duplicate elements from an array. + +{% multicode %} +```js +Operator.arrayUnique() +``` +```dart +Operator.arrayUnique() +``` +{% /multicode %} + +### arrayIntersect {% #array-intersect %} + +Keep only elements that exist in both arrays. + +{% multicode %} +```js +Operator.arrayIntersect(['news', 'tech']) +``` +```dart +Operator.arrayIntersect(['news', 'tech']) +``` +{% /multicode %} + +### arrayDiff {% #array-diff %} + +Return elements that exist in the current array but not in the provided array. + +{% multicode %} +```js +Operator.arrayDiff(['old']) +``` +```dart +Operator.arrayDiff(['old']) +``` +{% /multicode %} + +### arrayFilter {% #array-filter %} +Filter array elements based on a condition. + +{% multicode %} +```js +Operator.arrayFilter(Condition.GreaterThan, 10) +``` +```dart +Operator.arrayFilter(Condition.GreaterThan, 10) +``` +{% /multicode %} ## String operators {% #string %} Make lightweight text changes without rewriting the whole row. -| Name | Purpose | -|------|---------| -| `stringConcat` | Appends a string to the end of an existing string field | -| `stringReplace` | Replaces occurrences of a substring with a new string | +### stringConcat {% #string-concat %} + +Concatenate a value to a string or array field. + +{% multicode %} +```js +Operator.stringConcat('!') +``` +```dart +Operator.stringConcat('!') +``` +{% /multicode %} + +### stringReplace {% #string-replace %} +Replace occurrences of a substring with a new string. + +{% multicode %} +```js +Operator.stringReplace('old', 'new') +``` +```dart +Operator.stringReplace('old', 'new') +``` +{% /multicode %} ## Date operators {% #date %} Adjust time-based fields for lifecycle and scheduling logic. -| Name | Purpose | -|------|---------| -| `dateAddDays` | Adds a specified number of days to a date field | -| `dateSubDays` | Subtracts a specified number of days from a date field | -| `dateSetNow` | Sets a date field to a specific value | +### dateAddDays {% #date-add-days %} + +Add a specified number of days to a date field. + +{% multicode %} +```js +Operator.dateAddDays(7) +``` +```dart +Operator.dateAddDays(7) +``` +{% /multicode %} + +### dateSubDays {% #date-sub-days %} + +Subtract a specified number of days from a date field. + +{% multicode %} +```js +Operator.dateSubDays(3) +``` +```dart +Operator.dateSubDays(3) +``` +{% /multicode %} + +### dateSetNow {% #date-set-now %} + +Set a date field to the current time on the server. + +{% multicode %} +```js +Operator.dateSetNow() +``` +```dart +Operator.dateSetNow() +``` +{% /multicode %} + +## Boolean operators {% #boolean %} + +Toggle boolean values in place. + +### toggle {% #toggle %} + +Toggle a boolean field between true and false. + +{% multicode %} +```js +Operator.toggle() +``` +```dart +Operator.toggle() +``` +{% /multicode %} From acf0d9195fb81dd417b58e2a4a068b48c14cc3ab Mon Sep 17 00:00:00 2001 From: Aditya Oberai Date: Mon, 3 Nov 2025 17:01:52 +0000 Subject: [PATCH 09/13] Add Java, .NET, and PHP examples --- .../databases/db-operators/+page.markdoc | 817 ++++++++++++++++-- 1 file changed, 757 insertions(+), 60 deletions(-) diff --git a/src/routes/docs/products/databases/db-operators/+page.markdoc b/src/routes/docs/products/databases/db-operators/+page.markdoc index 818fab06b7..b774b50669 100644 --- a/src/routes/docs/products/databases/db-operators/+page.markdoc +++ b/src/routes/docs/products/databases/db-operators/+page.markdoc @@ -29,41 +29,258 @@ Let's take an example of appending a value to an array field. Here's how you can do so programmatically: {% multicode %} -```js +```client-web import { Client, TablesDB, Operator } from "appwrite"; const client = new Client() - .setEndpoint('https://.cloud.appwrite.io/v1') - .setProject(''); + .setEndpoint('https://.cloud.appwrite.io/v1') + .setProject(''); const tablesDB = new TablesDB(client); -const result = await tablesDB.updateRow({ - databaseId: "", - tableId: "", - rowId: "", - data: { - letters: Operator.arrayAppend(['c']) - } +await tablesDB.updateRow({ + databaseId: "", + tableId: "", + rowId: "", + data: { + letters: Operator.arrayAppend(['c']) + } }); ``` +```server-nodejs +const sdk = require('node-appwrite'); -```dart -import 'package:dart_appwrite/dart_appwrite.dart'; +const client = new sdk.Client(); +client + .setEndpoint('https://.cloud.appwrite.io/v1') + .setProject('') + .setKey(''); -final client = Client() - .setEndpoint('https://.cloud.appwrite.io/v1') - .setProject(''); +const tablesDB = new sdk.TablesDB(client); -final tablesDB = TablesDB(client); - -final result = await tablesDB.updateRow( +const result = await tablesDB.updateRow({ databaseId: '', tableId: '', rowId: '', data: { - 'letters': Operator.arrayAppend(['c']), - }, + letters: sdk.Operator.arrayAppend(['c']) + } +}); +``` +```client-flutter +import 'package:appwrite/appwrite.dart'; + +void main() async { + final client = Client() + .setEndpoint('https://.cloud.appwrite.io/v1') + .setProject(''); + + final tablesDB = TablesDB(client); + + try { + await tablesDB.updateRow( + '', + '', + '', + { + 'letters': Operator.arrayAppend(['c']) + }, + ); + } on AppwriteException catch (e) { + print(e); + } +} +``` +```client-apple +import Appwrite +import AppwriteModels + +func main() async throws { + let client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") + .setProject("") + + let tablesDB = TablesDB(client) + + do { + _ = try await tablesDB.updateRow( + databaseId: "", + tableId: "", + rowId: "", + data: [ + "letters": Operator.arrayAppend(["c"]) + ] + ) + } catch { + print(error.localizedDescription) + } +} +``` +```client-android-kotlin +import io.appwrite.Client +import io.appwrite.services.TablesDB +import io.appwrite.Operator + +suspend fun main() { + val client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") + .setProject("") + + val tablesDB = TablesDB(client) + + tablesDB.updateRow( + databaseId = "", + tableId = "", + rowId = "", + data = mapOf( + "letters" to Operator.arrayAppend(listOf("c")) + ) + ) +} +``` +```server-go +package main + +import ( + "log" + "github.com/appwrite/sdk-for-go/appwrite" + operator "github.com/appwrite/sdk-for-go/operator" +) + +func main() { + client := appwrite.NewClient( + appwrite.WithEndpoint("https://.cloud.appwrite.io/v1"), + appwrite.WithProject(""), + appwrite.WithKey(""), + ) + + tablesDB := appwrite.NewTablesDB(client) + + _, err := tablesDB.UpdateRow( + "", + "", + "", + tablesDB.WithUpdateRowData(map[string]any{ + "letters": operator.ArrayAppend([]string{"c"}), + }), + ) + if err != nil { + log.Fatal(err) + } +} +``` +```server-php +setEndpoint('https://.cloud.appwrite.io/v1') + ->setProject('') + ->setKey(''); + +$tablesDB = new TablesDB($client); + +$result = $tablesDB->updateRow( + '', + '', + '', + [ 'letters' => Operator::arrayAppend(['c']) ] +); +``` +```server-python +from appwrite.client import Client +from appwrite.services.tablesDB import TablesDB +from appwrite.operator import Operator + +client = Client() +(client + .set_endpoint('https://.cloud.appwrite.io/v1') + .set_project('') + .set_key('')) + +tablesDB = TablesDB(client) + +result = tablesDB.update_row( + '', + '', + '', + { 'letters': Operator.arrayAppend(['c']) } +) +``` +```server-dotnet +using Appwrite; +using Appwrite.Services; + +var client = new Client() + .SetEndpoint("https://.cloud.appwrite.io/v1") + .SetProject("") + .SetKey(""); + +var tablesDB = new TablesDB(client); + +await tablesDB.UpdateRow( + databaseId: "", + tableId: "", + rowId: "", + data: new Dictionary + { + { "letters", Operator.ArrayAppend(new[] { "c" }) } + } +); +``` +```server-ruby +require 'appwrite' + +include Appwrite + +client = Client.new() + +client + .set_endpoint('https://.cloud.appwrite.io/v1') + .set_project('') + .set_key('') + +tablesDB = TablesDB.new(client) + +result = tablesDB.update_row( + '', + '', + '', + { 'letters' => Operator.arrayAppend(['c']) } +) +``` +```server-java +import io.appwrite.Client; +import io.appwrite.coroutines.CoroutineCallback; +import io.appwrite.services.TablesDB; +import io.appwrite.Operator; +import java.util.*; + +Client client = new Client() + .setEndpoint("https://.cloud.appwrite.io/v1") + .setProject("") + .setKey(""); + +TablesDB tablesDB = new TablesDB(client); + +Map data = new HashMap<>(); +data.put("letters", Operator.arrayAppend(new String[] {"c"})); + +tablesDB.updateRow( + "", + "", + "", + data, + new CoroutineCallback<>((result, error) -> { + if (error != null) { + error.printStackTrace(); + return; + } + System.out.println(result); + }) ); ``` {% /multicode %} @@ -93,10 +310,34 @@ Perform arithmetic on numeric fields without reading the row first. Increase a numeric field by a specified value. Optionally cap the result at a maximum value. {% multicode %} -```js +```client-web +Operator.increment(1) +``` +```server-python Operator.increment(1) ``` -```dart +```server-php +Operator::increment(1) +``` +```client-apple +Operator.increment(1) +``` +```client-android-kotlin +Operator.increment(1) +``` +```server-go +operator.Increment(1) +``` +```client-flutter +Operator.increment(1) +``` +```server-dotnet +Operator.Increment(1) +``` +```server-ruby +Operator.increment(1) +``` +```server-java Operator.increment(1) ``` {% /multicode %} @@ -106,10 +347,34 @@ Operator.increment(1) Decrease a numeric field by a specified value. Optionally cap the result at a minimum value. {% multicode %} -```js +```client-web +Operator.decrement(1) +``` +```server-python +Operator.decrement(1) +``` +```server-php +Operator::decrement(1) +``` +```client-apple Operator.decrement(1) ``` -```dart +```client-android-kotlin +Operator.decrement(1) +``` +```server-go +operator.Decrement(1) +``` +```client-flutter +Operator.decrement(1) +``` +```server-dotnet +Operator.Decrement(1) +``` +```server-ruby +Operator.decrement(1) +``` +```server-java Operator.decrement(1) ``` {% /multicode %} @@ -119,10 +384,34 @@ Operator.decrement(1) Multiply a numeric field by a specified factor. Optionally cap the result at a maximum value. {% multicode %} -```js +```client-web +Operator.multiply(2) +``` +```server-python +Operator.multiply(2) +``` +```server-php +Operator::multiply(2) +``` +```client-apple +Operator.multiply(2) +``` +```client-android-kotlin Operator.multiply(2) ``` -```dart +```server-go +operator.Multiply(2) +``` +```client-flutter +Operator.multiply(2) +``` +```server-dotnet +Operator.Multiply(2) +``` +```server-ruby +Operator.multiply(2) +``` +```server-java Operator.multiply(2) ``` {% /multicode %} @@ -132,10 +421,34 @@ Operator.multiply(2) Divide a numeric field by a specified divisor. Optionally cap the result at a minimum value. Divisor cannot be zero. {% multicode %} -```js +```client-web +Operator.divide(5) +``` +```server-python +Operator.divide(5) +``` +```server-php +Operator::divide(5) +``` +```client-apple +Operator.divide(5) +``` +```client-android-kotlin +Operator.divide(5) +``` +```server-go +operator.Divide(5) +``` +```client-flutter +Operator.divide(5) +``` +```server-dotnet +Operator.Divide(5) +``` +```server-ruby Operator.divide(5) ``` -```dart +```server-java Operator.divide(5) ``` {% /multicode %} @@ -145,10 +458,34 @@ Operator.divide(5) Set a numeric field to the remainder of itself divided by a specified value. {% multicode %} -```js +```client-web Operator.modulo(3) ``` -```dart +```server-python +Operator.modulo(3) +``` +```server-php +Operator::modulo(3) +``` +```client-apple +Operator.modulo(3) +``` +```client-android-kotlin +Operator.modulo(3) +``` +```server-go +operator.Modulo(3) +``` +```client-flutter +Operator.modulo(3) +``` +```server-dotnet +Operator.Modulo(3) +``` +```server-ruby +Operator.modulo(3) +``` +```server-java Operator.modulo(3) ``` {% /multicode %} @@ -158,10 +495,34 @@ Operator.modulo(3) Raise a numeric field to a specified exponent. Optionally cap the result at a maximum value. {% multicode %} -```js +```client-web +Operator.power(2) +``` +```server-python Operator.power(2) ``` -```dart +```server-php +Operator::power(2) +``` +```client-apple +Operator.power(2) +``` +```client-android-kotlin +Operator.power(2) +``` +```server-go +operator.Power(2) +``` +```client-flutter +Operator.power(2) +``` +```server-dotnet +Operator.Power(2) +``` +```server-ruby +Operator.power(2) +``` +```server-java Operator.power(2) ``` {% /multicode %} @@ -175,12 +536,36 @@ Edit lists in place: append, remove, or modify array items atomically. Add one or more elements to the end of an array. {% multicode %} -```js +```client-web +Operator.arrayAppend(['c']) +``` +```server-python +Operator.arrayAppend(['c']) +``` +```server-php +Operator::arrayAppend(['c']) +``` +```client-apple +Operator.arrayAppend(["c"]) +``` +```client-android-kotlin +Operator.arrayAppend(listOf("c")) +``` +```server-go +operator.ArrayAppend([]string{"c"}) +``` +```client-flutter Operator.arrayAppend(['c']) ``` -```dart +```server-dotnet +Operator.ArrayAppend(new[] { "c" }) +``` +```server-ruby Operator.arrayAppend(['c']) ``` +```server-java +Operator.arrayAppend(new String[] {"c"}) +``` {% /multicode %} ### arrayPrepend {% #array-prepend %} @@ -188,12 +573,36 @@ Operator.arrayAppend(['c']) Add one or more elements to the beginning of an array. {% multicode %} -```js +```client-web Operator.arrayPrepend(['z']) ``` -```dart +```server-python Operator.arrayPrepend(['z']) ``` +```server-php +Operator::arrayPrepend(['z']) +``` +```client-apple +Operator.arrayPrepend(["z"]) +``` +```client-android-kotlin +Operator.arrayPrepend(listOf("z")) +``` +```server-go +operator.ArrayPrepend([]string{"z"}) +``` +```client-flutter +Operator.arrayPrepend(['z']) +``` +```server-dotnet +Operator.ArrayPrepend(new[] { "z" }) +``` +```server-ruby +Operator.arrayPrepend(['z']) +``` +```server-java +Operator.arrayPrepend(new String[] {"z"}) +``` {% /multicode %} ### arrayInsert {% #array-insert %} @@ -201,12 +610,36 @@ Operator.arrayPrepend(['z']) Insert an element at a specific index in an array. {% multicode %} -```js +```client-web Operator.arrayInsert(1, 'x') ``` -```dart +```server-python Operator.arrayInsert(1, 'x') ``` +```server-php +Operator::arrayInsert(1, 'x') +``` +```client-apple +Operator.arrayInsert(1, "x") +``` +```client-android-kotlin +Operator.arrayInsert(1, "x") +``` +```server-go +operator.ArrayInsert(1, "x") +``` +```client-flutter +Operator.arrayInsert(1, 'x') +``` +```server-dotnet +Operator.ArrayInsert(1, "x") +``` +```server-ruby +Operator.arrayInsert(1, 'x') +``` +```server-java +Operator.arrayInsert(1, "x") +``` {% /multicode %} ### arrayRemove {% #array-remove %} @@ -214,12 +647,36 @@ Operator.arrayInsert(1, 'x') Remove a specified element from an array. {% multicode %} -```js +```client-web Operator.arrayRemove('b') ``` -```dart +```server-python Operator.arrayRemove('b') ``` +```server-php +Operator::arrayRemove('b') +``` +```client-apple +Operator.arrayRemove("b") +``` +```client-android-kotlin +Operator.arrayRemove("b") +``` +```server-go +operator.ArrayRemove("b") +``` +```client-flutter +Operator.arrayRemove('b') +``` +```server-dotnet +Operator.ArrayRemove("b") +``` +```server-ruby +Operator.arrayRemove('b') +``` +```server-java +Operator.arrayRemove("b") +``` {% /multicode %} ### arrayUnique {% #array-unique %} @@ -227,10 +684,34 @@ Operator.arrayRemove('b') Remove duplicate elements from an array. {% multicode %} -```js +```client-web Operator.arrayUnique() ``` -```dart +```server-python +Operator.arrayUnique() +``` +```server-php +Operator::arrayUnique() +``` +```client-apple +Operator.arrayUnique() +``` +```client-android-kotlin +Operator.arrayUnique() +``` +```server-go +operator.ArrayUnique() +``` +```client-flutter +Operator.arrayUnique() +``` +```server-dotnet +Operator.ArrayUnique() +``` +```server-ruby +Operator.arrayUnique() +``` +```server-java Operator.arrayUnique() ``` {% /multicode %} @@ -240,12 +721,36 @@ Operator.arrayUnique() Keep only elements that exist in both arrays. {% multicode %} -```js +```client-web +Operator.arrayIntersect(['news', 'tech']) +``` +```server-python +Operator.arrayIntersect(['news', 'tech']) +``` +```server-php +Operator::arrayIntersect(['news', 'tech']) +``` +```client-apple +Operator.arrayIntersect(["news", "tech"]) +``` +```client-android-kotlin +Operator.arrayIntersect(listOf("news", "tech")) +``` +```server-go +operator.ArrayIntersect([]string{"news", "tech"}) +``` +```client-flutter Operator.arrayIntersect(['news', 'tech']) ``` -```dart +```server-dotnet +Operator.ArrayIntersect(new[] { "news", "tech" }) +``` +```server-ruby Operator.arrayIntersect(['news', 'tech']) ``` +```server-java +Operator.arrayIntersect(new String[] {"news", "tech"}) +``` {% /multicode %} ### arrayDiff {% #array-diff %} @@ -253,12 +758,36 @@ Operator.arrayIntersect(['news', 'tech']) Return elements that exist in the current array but not in the provided array. {% multicode %} -```js +```client-web Operator.arrayDiff(['old']) ``` -```dart +```server-python Operator.arrayDiff(['old']) ``` +```server-php +Operator::arrayDiff(['old']) +``` +```client-apple +Operator.arrayDiff(["old"]) +``` +```client-android-kotlin +Operator.arrayDiff(listOf("old")) +``` +```server-go +operator.ArrayDiff([]string{"old"}) +``` +```client-flutter +Operator.arrayDiff(['old']) +``` +```server-dotnet +Operator.ArrayDiff(new[] { "old" }) +``` +```server-ruby +Operator.arrayDiff(['old']) +``` +```server-java +Operator.arrayDiff(new String[] {"old"}) +``` {% /multicode %} ### arrayFilter {% #array-filter %} @@ -266,10 +795,34 @@ Operator.arrayDiff(['old']) Filter array elements based on a condition. {% multicode %} -```js +```client-web +Operator.arrayFilter(Condition.GreaterThan, 10) +``` +```server-python Operator.arrayFilter(Condition.GreaterThan, 10) ``` -```dart +```server-php +Operator::arrayFilter(Condition::GreaterThan, 10) +``` +```client-apple +Operator.arrayFilter(Condition.GreaterThan, 10) +``` +```client-android-kotlin +Operator.arrayFilter(Condition.GreaterThan, 10) +``` +```server-go +operator.ArrayFilter(ConditionGreaterThan, 10) +``` +```client-flutter +Operator.arrayFilter(Condition.GreaterThan, 10) +``` +```server-dotnet +Operator.ArrayFilter(Condition.GreaterThan, 10) +``` +```server-ruby +Operator.arrayFilter(Condition.GreaterThan, 10) +``` +```server-java Operator.arrayFilter(Condition.GreaterThan, 10) ``` {% /multicode %} @@ -283,12 +836,36 @@ Make lightweight text changes without rewriting the whole row. Concatenate a value to a string or array field. {% multicode %} -```js +```client-web Operator.stringConcat('!') ``` -```dart +```server-python Operator.stringConcat('!') ``` +```server-php +Operator::stringConcat('!') +``` +```client-apple +Operator.stringConcat("!") +``` +```client-android-kotlin +Operator.stringConcat("!") +``` +```server-go +operator.StringConcat("!") +``` +```client-flutter +Operator.stringConcat('!') +``` +```server-dotnet +Operator.StringConcat("!") +``` +```server-ruby +Operator.stringConcat('!') +``` +```server-java +Operator.stringConcat("!") +``` {% /multicode %} ### stringReplace {% #string-replace %} @@ -296,12 +873,36 @@ Operator.stringConcat('!') Replace occurrences of a substring with a new string. {% multicode %} -```js +```client-web Operator.stringReplace('old', 'new') ``` -```dart +```server-python Operator.stringReplace('old', 'new') ``` +```server-php +Operator::stringReplace('old', 'new') +``` +```client-apple +Operator.stringReplace("old", "new") +``` +```client-android-kotlin +Operator.stringReplace("old", "new") +``` +```server-go +operator.StringReplace("old", "new") +``` +```client-flutter +Operator.stringReplace('old', 'new') +``` +```server-dotnet +Operator.StringReplace("old", "new") +``` +```server-ruby +Operator.stringReplace('old', 'new') +``` +```server-java +Operator.stringReplace("old", "new") +``` {% /multicode %} ## Date operators {% #date %} @@ -313,10 +914,34 @@ Adjust time-based fields for lifecycle and scheduling logic. Add a specified number of days to a date field. {% multicode %} -```js +```client-web +Operator.dateAddDays(7) +``` +```server-python Operator.dateAddDays(7) ``` -```dart +```server-php +Operator::dateAddDays(7) +``` +```client-apple +Operator.dateAddDays(7) +``` +```client-android-kotlin +Operator.dateAddDays(7) +``` +```server-go +operator.DateAddDays(7) +``` +```client-flutter +Operator.dateAddDays(7) +``` +```server-dotnet +Operator.DateAddDays(7) +``` +```server-ruby +Operator.dateAddDays(7) +``` +```server-java Operator.dateAddDays(7) ``` {% /multicode %} @@ -326,10 +951,34 @@ Operator.dateAddDays(7) Subtract a specified number of days from a date field. {% multicode %} -```js +```client-web +Operator.dateSubDays(3) +``` +```server-python Operator.dateSubDays(3) ``` -```dart +```server-php +Operator::dateSubDays(3) +``` +```client-apple +Operator.dateSubDays(3) +``` +```client-android-kotlin +Operator.dateSubDays(3) +``` +```server-go +operator.DateSubDays(3) +``` +```client-flutter +Operator.dateSubDays(3) +``` +```server-dotnet +Operator.DateSubDays(3) +``` +```server-ruby +Operator.dateSubDays(3) +``` +```server-java Operator.dateSubDays(3) ``` {% /multicode %} @@ -339,10 +988,34 @@ Operator.dateSubDays(3) Set a date field to the current time on the server. {% multicode %} -```js +```client-web Operator.dateSetNow() ``` -```dart +```server-python +Operator.dateSetNow() +``` +```server-php +Operator::dateSetNow() +``` +```client-apple +Operator.dateSetNow() +``` +```client-android-kotlin +Operator.dateSetNow() +``` +```server-go +operator.DateSetNow() +``` +```client-flutter +Operator.dateSetNow() +``` +```server-dotnet +Operator.DateSetNow() +``` +```server-ruby +Operator.dateSetNow() +``` +```server-java Operator.dateSetNow() ``` {% /multicode %} @@ -356,10 +1029,34 @@ Toggle boolean values in place. Toggle a boolean field between true and false. {% multicode %} -```js +```client-web +Operator.toggle() +``` +```server-python +Operator.toggle() +``` +```server-php +Operator::toggle() +``` +```client-apple +Operator.toggle() +``` +```client-android-kotlin +Operator.toggle() +``` +```server-go +operator.Toggle() +``` +```client-flutter +Operator.toggle() +``` +```server-dotnet +Operator.Toggle() +``` +```server-ruby Operator.toggle() ``` -```dart +```server-java Operator.toggle() ``` {% /multicode %} From c150a0cd3cedeefc4f18048881ae17fd8e78e620 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Tue, 4 Nov 2025 20:16:13 +1300 Subject: [PATCH 10/13] Update src/routes/docs/products/databases/db-operators/+page.markdoc Co-authored-by: Aditya Oberai --- .../docs/products/databases/db-operators/+page.markdoc | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/routes/docs/products/databases/db-operators/+page.markdoc b/src/routes/docs/products/databases/db-operators/+page.markdoc index b774b50669..c5c90cd3d4 100644 --- a/src/routes/docs/products/databases/db-operators/+page.markdoc +++ b/src/routes/docs/products/databases/db-operators/+page.markdoc @@ -266,14 +266,11 @@ Client client = new Client() TablesDB tablesDB = new TablesDB(client); -Map data = new HashMap<>(); -data.put("letters", Operator.arrayAppend(new String[] {"c"})); - tablesDB.updateRow( "", "", "", - data, + Map.of("letters", Operator.arrayAppend(List.of("c"))), new CoroutineCallback<>((result, error) -> { if (error != null) { error.printStackTrace(); From c01307fe3c9d45abc5c6d52feb90508a8ce3f8b4 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Tue, 4 Nov 2025 20:16:37 +1300 Subject: [PATCH 11/13] Update src/routes/docs/products/databases/db-operators/+page.markdoc Co-authored-by: Aditya Oberai --- src/routes/docs/products/databases/db-operators/+page.markdoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/routes/docs/products/databases/db-operators/+page.markdoc b/src/routes/docs/products/databases/db-operators/+page.markdoc index c5c90cd3d4..d6776ae8c3 100644 --- a/src/routes/docs/products/databases/db-operators/+page.markdoc +++ b/src/routes/docs/products/databases/db-operators/+page.markdoc @@ -598,7 +598,7 @@ Operator.ArrayPrepend(new[] { "z" }) Operator.arrayPrepend(['z']) ``` ```server-java -Operator.arrayPrepend(new String[] {"z"}) +Operator.arrayPrepend(List.of("c")) ``` {% /multicode %} From 4d6050b234c846c55a7fd41305ae733093a54f8d Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Tue, 4 Nov 2025 20:16:55 +1300 Subject: [PATCH 12/13] Update src/routes/docs/products/databases/db-operators/+page.markdoc Co-authored-by: Aditya Oberai --- src/routes/docs/products/databases/db-operators/+page.markdoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/routes/docs/products/databases/db-operators/+page.markdoc b/src/routes/docs/products/databases/db-operators/+page.markdoc index d6776ae8c3..c25e709944 100644 --- a/src/routes/docs/products/databases/db-operators/+page.markdoc +++ b/src/routes/docs/products/databases/db-operators/+page.markdoc @@ -561,7 +561,7 @@ Operator.ArrayAppend(new[] { "c" }) Operator.arrayAppend(['c']) ``` ```server-java -Operator.arrayAppend(new String[] {"c"}) +Operator.arrayAppend(List.of("c")) ``` {% /multicode %} From 5e242d59208e4007c863c56bfecd90d2966b74d8 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Tue, 4 Nov 2025 20:21:11 +1300 Subject: [PATCH 13/13] Update src/routes/docs/products/databases/db-operators/+page.markdoc Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- src/routes/docs/products/databases/db-operators/+page.markdoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/routes/docs/products/databases/db-operators/+page.markdoc b/src/routes/docs/products/databases/db-operators/+page.markdoc index c25e709944..2d7817826e 100644 --- a/src/routes/docs/products/databases/db-operators/+page.markdoc +++ b/src/routes/docs/products/databases/db-operators/+page.markdoc @@ -598,7 +598,7 @@ Operator.ArrayPrepend(new[] { "z" }) Operator.arrayPrepend(['z']) ``` ```server-java -Operator.arrayPrepend(List.of("c")) +Operator.arrayPrepend(List.of("z")) ``` {% /multicode %}