NOsql Object (NO2 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 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:
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:
dart pub add nitrite_hive_adapter
More on the module API can be found here.
✍️ Usage
To create a new database or open an existing database, use the builder API to create a database instance:
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.
// 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 is a simple key-value pair. To store a document in a collection, use the following code:
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.
📦 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.
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:
dart pub add nitrite_generator --dev
dart pub add build_runner --dev
More on ObjectRepository
can be found in guide here.
📇 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,
// 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.
// 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 in the guide.
🤝 Transaction
Nitrite has support for transaction on NitriteCollection
and ObjectRepository
. Transactions can be used as follows:
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.
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. The project is open source and available in GitHub. If you have any questions, please feel free to ask in GitHub Discussions.
Top comments (0)