Introducing Nitrite for Flutter : An embedded NoSQL database for Flutter
Tags: flutter, nosql, database, opensource
Published: 2024-01-20 07:48:20

**NO**sql **O**bject (NO<sub>2</sub> a.k.a. Nitrite) is a server-less, embedded, and self-contained NoSQL database. It is an open-source project that provides a simple API for persistent data storage. Nitrite database is designed to be lightweight, fast, and easy to use. Apart from Flutter it is available in Java and Kotlin as well.

Nitrite database can be used in various scenarios where a lightweight, embedded, and server-less NoSQL database is required. Some of the use cases for Nitrite database are:

- Mobile and desktop applications
- IoT devices and sensors
- Web applications and APIs
- Prototyping and testing
- Data caching and synchronization
- Data analysis and reporting

Nitrite database is designed to be simple and easy to use, making it an ideal choice for Flutter applications. Nitrite is written in pure Dart without any native dependencies.

### ✨ Features

- Embedded, server-less
- Simple API
- Document-oriented
- Schema-less document collection and object repository
- Extensible storage engines
- Indexing and full-text search
- Simple query API
- In-memory and file-based store
- Transaction support
- Schema migration support
- Encryption support

Nitrite also comes with a well written [documentation](https://nitrite.dizitart.com/flutter-sdk/getting-started/index.html) with lots of examples to get you started.


### 🚀 Getting Started

Nitrite is a pure Dart database. It does not depend on any native library. So it can be used in any platform where Dart is supported. It is a server-less embedded database ideal for desktop, mobile, or web applications. It is written in pure Dart and runs in Flutter, Dart VM, and the browser. To use Nitrite in your project, add the following package to your package:

```bash
dart pub add nitrite
```

By design, Nitrite is modular and extensible. It has a core module which provides all the basic features. Additional features like persistent storage, spatial indexing, encryption etc. are available as separate modules. You only need to add the modules you need.

As for example, if you want to use Nitrite with persistent storage, add the following additional dependency in your project:

```bash
dart pub add nitrite_hive_adapter
```

More on the module API can be found [here](https://nitrite.dizitart.com/flutter-sdk/modules/module-system/index.html).

### ✍️ Usage 

To create a new database or open an existing database, use the builder API to create a database instance:

```dart
import 'package:nitrite/nitrite.dart';

var db = await Nitrite.builder()
    .openOrCreate(username: 'user', password: 'pass123');
```
By default, Nitrite uses in-memory storage. To use persistent storage, load a persistent storage module. Nitrite provides a persistent storage module based on Hive.

```dart
// create a hive backed storage module
var storeModule = HiveModule.withConfig()
    .crashRecovery(true)
    .path('$dbDir/db')
    .build();


// initialization using builder
var db = await Nitrite.builder()
    .loadModule(storeModule)
    .openOrCreate(username: 'user', password: 'pass123');
```

### 🗂️ Nitrite Collection

Nitrite stores data as a collection of documents. A [Document](https://nitrite.dizitart.com/flutter-sdk/document/index.html) is a simple key-value pair. To store a document in a collection, use the following code:

```dart
var coll = await db.collection('test');

// create a document
var document = createDocument("firstName", "John")
    .put("phone", ["212-555-1234", "646-555-4567"]);

// insert the document
await coll.insert(document);
```

More on the `NitriteCollection` is available [here](https://nitrite.dizitart.com/flutter-sdk/collection/intro/index.html).

### 📦 Object Repository

Nitrite also provides `ObjectRepository` which is nothing but a abstraction over `NitriteCollection` to store Dart objects. Nitrite uses converters to map a Dart object to a document and stores it in a collection.

```dart
var repo = await db.getRepository<Person>();

// create a person object
var person = Person()
    ..firstName = 'John'
    ..lastName = 'Doe'
    ..age = 30
    ..address = Address()
      ..street = '21 2nd Street'
      ..city = 'New York'
      ..state = 'NY'
      ..country = 'USA'
      ..zip = '10021';

// insert the person object
await repo.insert(person);
```

You can either write your own converter or use the Nitrite’s code generator to generate the converter for you. To use the code generator, add the following dev dependencies in your project:

```bash
dart pub add nitrite_generator --dev
dart pub add build_runner --dev
```

More on `ObjectRepository` can be found in guide [here](https://nitrite.dizitart.com/flutter-sdk/repository/intro/index.html).

### 📇 Indexing

Nitrite supports indexing on single or multiple fields to optimize the performance of a database by minimizing the number of disk accesses required when a query is processed. It supports following types of indexes:

- Unique Index
- Non-Unique Index
- Full-text Index
- Spatial Index via spatial module

You can even create your own custom index using the Module API. To create an index on a field,

```dart
// create a non-unique index on field 'firstName'
await coll.createIndex(['firstName'], indexOptions(IndexType.nonUnique));

// create a full-text index on field 'note'
await coll.createIndex(['note'], indexOptions(IndexType.fullText));

// create a unique index on field 'phone' and 'email'
await coll.createIndex(['phone', 'email']);
```

### 🔍 Query

Nitrite provides a fluent API for find operation. It also provides a simple query DSL based on Dart language features like extension methods and operator overloading.

```dart
// find all documents where firstName is 'John'
var cursor = coll.find(filter: where('firstName').eq('John'));

// find all documents where firstName is 'John' and age is greater than 25
var cursor = coll.find(filter: 'name'.eq('John') & 'age' > 18);
```

Extensive details about all types of Filters and example can be found [here](https://nitrite.dizitart.com/flutter-sdk/filter/index.html) in the guide.

### 🤝 Transaction

Nitrite has support for transaction on `NitriteCollection` and `ObjectRepository`. Transactions can be used as follows:

```dart
var session = db.createSession();

await session.executeTransaction((transaction) async {
  var collection = await transaction.getCollection("test");
  await collection.insert(doc1);
}, rollbackFor: [NitriteException]);
```

More on transaction can be found [here](https://nitrite.dizitart.com/flutter-sdk/transaction/index.html).

There are many more features available in Nitrite which cannot be covered in this short introduction. To learn more about Nitrite, please visit the [documentation](https://nitrite.dizitart.com/index.html). The project is open source and available in [GitHub](https://github.com/nitrite/nitrite-flutter). If you have any questions, please feel free to ask in [GitHub Discussions](https://github.com/orgs/nitrite/discussions).