Skip to content

chore: change examples to use cursor get by column name: #106

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Feb 6, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions client-sdk-references/kotlin-multiplatform.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -242,9 +242,9 @@ fun watchCustomers(): Flow<List<User>> {
// TODO: implement your UI based on the result set
return database.watch("SELECT * FROM customers", mapper = { cursor ->
User(
id = cursor.getString(0)!!,
name = cursor.getString(1)!!,
email = cursor.getString(2)!!
id = cursor.getString("id"),
name = cursor.getString("name"),
email = cursor.getString("email")
)
})
}
Expand Down
6 changes: 3 additions & 3 deletions client-sdk-references/kotlin-multiplatform/usage-examples.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@ fun watchCustomers(): Flow<List<User>> {
// TODO: implement your UI based on the result set
return database.watch("SELECT * FROM customers", mapper = { cursor ->
User(
id = cursor.getString(0)!!,
name = cursor.getString(1)!!,
email = cursor.getString(2)!!
id = cursor.getString("id"),
name = cursor.getString("name"),
email = cursor.getString("email")
)
})
}
Expand Down
26 changes: 13 additions & 13 deletions client-sdk-references/swift.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ sidebarTitle: "Overview"
<CardGroup cols={3}>
<Card title="Source Code" icon="github" href="https://github.com/powersync-ja/powersync-swift/">
Refer to the powersync-swift repo on GitHub.
</Card>
</Card>
<Card title="API Reference (Coming soon)" icon="book" href="">
A full API Reference for this SDK is not yet available. This is planned for the V1 release.
</Card>
Expand Down Expand Up @@ -249,10 +249,10 @@ func getList(_ id: String) async throws {
parameters: [id],
mapper: { cursor in
ListContent(
id: cursor.getString(index: 0)!,
name: cursor.getString(index: 1)!,
createdAt: cursor.getString(index: 2)!,
ownerId: cursor.getString(index: 3)!
id: try cursor.getString(name: "id")!,
name: try cursor.getString(name: "name")!,
createdAt: try cursor.getString(name: "created_at")!,
ownerId: try cursor.getString(name: "owner_id")!
)
}
)
Expand All @@ -271,10 +271,10 @@ func getLists() async throws {
parameters: [],
mapper: { cursor in
ListContent(
id: cursor.getString(index: 0)!,
name: cursor.getString(index: 1)!,
createdAt: cursor.getString(index: 2)!,
ownerId: cursor.getString(index: 3)!
id: try cursor.getString(name: "id")!,
name: try cursor.getString(name: "name")!,
createdAt: try cursor.getString(name: "created_at")!,
ownerId: try cursor.getString(name: "owner_id")!
)
}
)
Expand All @@ -293,10 +293,10 @@ func watchLists(_ callback: @escaping (_ lists: [ListContent]) -> Void ) async {
parameters: [],
mapper: { cursor in
ListContent(
id: cursor.getString(index: 0)!,
name: cursor.getString(index: 1)!,
createdAt: cursor.getString(index: 2)!,
ownerId: cursor.getString(index: 3)!
id: try cursor.getString(name: "id")!,
name: try cursor.getString(name: "name")!,
createdAt: try cursor.getString(name: "created_at")!,
ownerId: try cursor.getString(name: "owner_id")!
)
}
) {
Expand Down
64 changes: 32 additions & 32 deletions migration-guides/mongodb-atlas.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ Here is a quick overview of the resulting PowerSync architecture:
* **PowerSync Client SDKs** use **SQLite** under the hood. Even though MongoDB is a “NoSQL” document database, PowerSync’s use of SQLite works well with MongoDB, since the [PowerSync protocol](/architecture/powersync-protocol) is schemaless (it syncs schemaless JSON data) and we dynamically apply a [client-side schema](/installation/client-side-setup/define-your-schema) to the data in SQLite using SQLite views. Client-side queries can be written in SQL or you can make use of an ORM (we provide a few [ORM integrations](https://www.powersync.com/blog/using-orms-with-powersync))
* **Reads vs Writes**: PowerSync handles syncing of reads differently from writes.
* **Reads**: The PowerSync Service connects to your MongoDB database and replicates data in real-time to PowerSync clients. Reads are configured using PowerSync’s [“Sync Rules”](/usage/sync-rules/). Sync Rules are more flexible than MongoDB Realm Flexible Sync, but are defined on the server-side, not on the client-side.
* **Writes**: The client-side application can perform writes directly on the local SQLite database. The writes are also automatically placed into an upload queue by the PowerSync Client SDK. The SDK then uses a developer-defined `uploadData()` function to manage the uploading of those writes sequentially to the backend.
* **Writes**: The client-side application can perform writes directly on the local SQLite database. The writes are also automatically placed into an upload queue by the PowerSync Client SDK. The SDK then uses a developer-defined `uploadData()` function to manage the uploading of those writes sequentially to the backend.
* **Authorization**: Authorization is controlled separately for reads vs. writes.
* **Reads**: The [Sync Rules](/usage/sync-rules/) control which users can access which data.
* **Writes**: The backend controls authorization for how users can modify data.
Expand All @@ -59,41 +59,41 @@ Here is a quick overview of the resulting PowerSync architecture:

## Migration Steps

Follow the steps below to migrate a MongoDB Atlas Device Sync app to PowerSync.
Follow the steps below to migrate a MongoDB Atlas Device Sync app to PowerSync.

### 1. Remove Realm

Before adding PowerSync, remove MongoDB Realm from your project. This includes uninstalling the Realm SDK and deleting all Realm-related code and dependencies. It is also possible to initially run Realm and PowerSync in parallel, and remove Realm later.

### 2. Create PowerSync account and instance

To get started quickly with PowerSync, sign up for a free PowerSync Cloud account [here](https://accounts.journeyapps.com/portal/powersync-signup?s=mongodb-migration-guide).
To get started quickly with PowerSync, sign up for a free PowerSync Cloud account [here](https://accounts.journeyapps.com/portal/powersync-signup?s=mongodb-migration-guide).

It is also possible to self-host PowerSync. An end-to-end demo app using Docker Compose is available [here](https://github.com/powersync-ja/self-host-demo/tree/main/demos/nodejs-mongodb).

### 3. Connect PowerSync to MongoDB

Once your account is set up, [create a new PowerSync instance](/installation/database-connection#create-a-powersync-cloud-instance) and configure the instance to connect to your source [MongoDB database](/installation/database-connection#mongodb-beta-specifics).
Once your account is set up, [create a new PowerSync instance](/installation/database-connection#create-a-powersync-cloud-instance) and configure the instance to connect to your source [MongoDB database](/installation/database-connection#mongodb-beta-specifics).

### 4. Define Sync Rules

Sync Rules allow you to control which data gets synced to which users/devices. Each PowerSync Service instance has a Sync Rules definition that consists of SQL-like queries in a YAML file.

To get a good understanding of how Sync Rules operate, have a look at our blog post: [Sync Rules from First Principles: Partial Replication to SQLite](https://www.powersync.com/blog/sync-rules-from-first-principles-partial-replication-to-sqlite).

If you have a PowerSync Service instance set up and connected, open the `sync-rules.yaml` file associated with your PowerSync project and edit the SQL-like queries based on your database schema. Below is a simple Sync Rules example using a simple database schema. Sync Rules involve organizing data into ["buckets"](/usage/sync-rules/organize-data-into-buckets) (a bucket is a grouping of data). The example below uses a ["global bucket"](/usage/sync-rules/example-global-data) as a simple starting point — data in a "global bucket" will be synced to all users.
If you have a PowerSync Service instance set up and connected, open the `sync-rules.yaml` file associated with your PowerSync project and edit the SQL-like queries based on your database schema. Below is a simple Sync Rules example using a simple database schema. Sync Rules involve organizing data into ["buckets"](/usage/sync-rules/organize-data-into-buckets) (a bucket is a grouping of data). The example below uses a ["global bucket"](/usage/sync-rules/example-global-data) as a simple starting point — data in a "global bucket" will be synced to all users.

<Info>Note that MongoDB uses “_id” as the name of the ID field in collections whereas PowerSync uses “id” in its client-side database. This is why `SELECT _id as id` should always be used in the data queries when pairing PowerSync with MongoDB.</Info>

```yaml
bucket_definitions:
# This is the name of the bucket, in this case the global bucket synced to all users.
global:
global:
# This is the query used to determine the data in each bucket
data:
data:
# Note that we select the MongoDB _id field as id
- SELECT _id as id, * FROM lists
- SELECT _id as id, * FROM todos
- SELECT _id as id, * FROM lists
- SELECT _id as id, * FROM todos
```

To filter data based on the user and other more advanced use cases, refer to the [Sync Rules documentation](/usage/sync-rules).
Expand All @@ -109,13 +109,13 @@ Add PowerSync to your app project by following the instructions for the relevant

The PowerSync client-side schema represents a “view” of the data synced from the PowerSync Service to the client app. No migrations are required — the schema is applied directly when the local PowerSync SQLite database is constructed.

To make this step easy for you, the [PowerSync Dashboard](/usage/tools/powersync-dashboard) allows automatically generating the client-side schema based on the Sync Rules defined for a PowerSync instance. To generate the schema, go to the [dashboard](https://powersync.journeyapps.com/), right-click on the instance, and select “Generate Client Schema”. Alternatively you can use the PowerSync [CLI](/usage/tools/cli) to generate the schema.
To make this step easy for you, the [PowerSync Dashboard](/usage/tools/powersync-dashboard) allows automatically generating the client-side schema based on the Sync Rules defined for a PowerSync instance. To generate the schema, go to the [dashboard](https://powersync.journeyapps.com/), right-click on the instance, and select “Generate Client Schema”. Alternatively you can use the PowerSync [CLI](/usage/tools/cli) to generate the schema.

Here is an example of a client-side schema for PowerSync using a simple `todos` table:

<CodeGroup>

```typescript TypeScript - React Native
```typescript TypeScript - React Native
import { column, Schema, Table } from '@powersync/react-native';

const todos = new Table(
Expand All @@ -127,14 +127,14 @@ Here is an example of a client-side schema for PowerSync using a simple `todos`
created_by: column.text,
completed_by: column.text,
completed: column.integer
},
},
{ indexes: { list: ['list_id'] } }
);

export const AppSchema = new Schema({
todos
});
```
```

```typescript TypeScript - Web
import { column, Schema, Table } from '@powersync/web';
Expand Down Expand Up @@ -212,7 +212,7 @@ Here is an example of a client-side schema for PowerSync using a simple `todos`
let AppSchema = Schema(todos)
```

```dart Flutter
```dart Flutter
import 'package:powersync/powersync.dart';

const schema = Schema(([
Expand All @@ -235,7 +235,7 @@ Here is an example of a client-side schema for PowerSync using a simple `todos`

A few things to note regarding the PowerSync client-side schema:

* The schema does not explicitly specify an `id` column, since the PowerSync automatically creates an `id` column of type `text`.
* The schema does not explicitly specify an `id` column, since the PowerSync automatically creates an `id` column of type `text`.
* SQLite has very simple data types which are [used by](/usage/sync-rules/types#types) PowerSync.
* For MongoDB specific data types, refer to [MongoDB Type Mapping](/usage/sync-rules/types#mongodb-beta-type-mapping).
* PowerSync also supports [syncing attachments or files](/usage/use-case-examples/attachments-files#attachments-files) using helper packages.
Expand All @@ -247,7 +247,7 @@ Now that we have our Sync Rules and client-side schema defined, we can instantia

<CodeGroup>

```typescript TypeScript - React Native
```typescript TypeScript - React Native
import { PowerSyncDatabase } from '@powersync/react-native';
import { Connector } from './Connector';
import { AppSchema } from './Schema';
Expand All @@ -263,7 +263,7 @@ Now that we have our Sync Rules and client-side schema defined, we can instantia
const connector = new Connector();
db.connect(connector);
};
```
```

```typescript TypeScript - Web
import { PowerSyncDatabase } from '@powersync/web';
Expand Down Expand Up @@ -322,7 +322,7 @@ Now that we have our Sync Rules and client-side schema defined, we can instantia
await db.connect(connector: connector);
```

```dart Flutter
```dart Flutter
import 'package:powersync/powersync.dart';
import 'package:path_provider/path_provider.dart';
import 'package:path/path.dart';
Expand All @@ -340,7 +340,7 @@ Now that we have our Sync Rules and client-side schema defined, we can instantia

### 8. Reading and writing data

Reading data in the application which uses PowerSync is very simple: we use SQLite syntax to query data in our local database.
Reading data in the application which uses PowerSync is very simple: we use SQLite syntax to query data in our local database.

<CodeGroup>

Expand All @@ -350,7 +350,7 @@ Reading data in the application which uses PowerSync is very simple: we use SQLi
const results = await db.getAll('SELECT * FROM todos');
return results;
}
```
```

```java Kotlin
// Reading Data
Expand All @@ -367,19 +367,19 @@ Reading data in the application which uses PowerSync is very simple: we use SQLi
sql: "SELECT * FROM todos",
mapper: { cursor in
TodoContent(
list_id: cursor.getString(index: 0)!,
description: cursor.getString(index: 1)!,
completed: cursor.getString(index: 2)!,
created_by: cursor.getString(index: 3)!,
completed_by: cursor.getString(index: 4)!,
completed_at: cursor.getString(index: 5)!
list_id: try cursor.getString(name: "list_id"),
description: try cursor.getString(name: "description"),
completed: try cursor.getBooleanOptional(name: "completed"),
created_by: try cursor.getString(name: "created_by"),
completed_by: try cursor.getStringOptional(name: "completed_by"),
completed_at: try cursor.getStringOptional(name: "completed_at")
)
}
)
}
```

```dart Flutter
```dart Flutter
/// Reading Data
Future<TodoList> getTodos() async {
final result = await db.get('SELECT * FROM todos');
Expand All @@ -398,7 +398,7 @@ The same applies to writing data: `INSERT`, `UPDATE` and `DELETE` statements are
export const insertTodo = async (listId: string, description: string) => {
await db.execute('INSERT INTO todos (id, created_at, list_id, description) VALUES (uuid(), date(), ?, ?)', [listId, description]);
}
```
```

```java Kotlin
// Writing Data
Expand All @@ -422,7 +422,7 @@ The same applies to writing data: `INSERT`, `UPDATE` and `DELETE` statements are
}
```

```dart Flutter
```dart Flutter
/// Writing Data
await db.execute(
'INSERT INTO todos (id, created_at, list_id, description) VALUES (uuid(), date(), ?, ?)',
Expand Down Expand Up @@ -452,7 +452,7 @@ There are two options:

#### Using PowerSync’s serverless cloud functions

PowerSync provides serverless cloud functions for backend functionality, with a template available for MongoDB. See the [step-by-step instructions](/usage/tools/cloudcode) on how to use the template. The template can be customized, or it can be used as-is.
PowerSync provides serverless cloud functions for backend functionality, with a template available for MongoDB. See the [step-by-step instructions](/usage/tools/cloudcode) on how to use the template. The template can be customized, or it can be used as-is.

The template provides [turnkey conflict resolution](https://www.powersync.com/blog/turnkey-backend-functionality-conflict-resolution-for-powersync#turnkey-conflict-resolution) which roughly matches the built-in conflict resolution behavior provided by MongoDB Atlas Device Sync.

Expand All @@ -465,7 +465,7 @@ For more information, see our blog post: [Turnkey Backend Functionality & Confli

This option gives you complete control over the backend. The simplest backend implementation is to simply apply writes to MongoDB as they are received, which results in a last-write-wins conflict resolution strategy (same as the “turnkey backend functionality” option above). See [Writing Client Changes](/installation/app-backend-setup/writing-client-changes) for more details.

On the client-side, you need to wire up the `uploadData()` function in the “backend connector” to use your own backend API. The [App Backend Setup](/installation/app-backend-setup) section of our docs provides step-by-step instructions for this.
On the client-side, you need to wire up the `uploadData()` function in the “backend connector” to use your own backend API. The [App Backend Setup](/installation/app-backend-setup) section of our docs provides step-by-step instructions for this.

Also see the section on [how to set up a simple backend API](https://www.powersync.com/blog/migrating-a-mongodb-atlas-device-sync-app-to-powersync#backend-api-setup) in our practical MongoDB migration [example](https://www.powersync.com/blog/migrating-a-mongodb-atlas-device-sync-app-to-powersync) on our blog.

Expand All @@ -474,4 +474,4 @@ We also have [example backend implementations](/resources/demo-apps-example-proj

## Questions? Need help?

[Get in touch](https://www.powersync.com/contact) with us.
[Get in touch](https://www.powersync.com/contact) with us.