A NoSQL embedded database for you Rust app
For a long time, SQLite has been the only choice for local embedded database. It’s stable and powerful. However. However, times are changing and demands are evolving rapidly. For rapid iteration of program functions, I believe that many apps need a scheme-less database. There are not many options for NoSQL local databases. If you are looking for one that, I suggest PoloDB.
Github: https://github.com/PoloDB/PoloDB
Get started
PoloDB is an embedded database written in Rust. If you are developing an app in Rust, PoloDB would be a perfect fit for you. This is because Rust’s API has been designed with compatibility with MongoDB in mind, making PoloDB essentially compatible with MongoDB.
Let’s look at the example:
use polodb_core::Database;
use serde::{Serialize, Deserialize};
#[derive(Debug, Serialize, Deserialize)]
struct Book {
title: String,
author: String,
}
let db = Database::open_file(db_path)?;
let collection = db.collection::<Book>("books");
collection.insert_one(Book {
title: "The Three-Body Problem".to_string(),
author: "Liu Cixin".to_string(),
})?;
In the above example, the Book
structure is serialized into BSON format and persisted on the disk. Since PoloDB is schema-less, it's not required to create a table for it in SQLite. It's free to insert any form of data.
For example, you can insert a document structure directly:
let typed_collection = db.collection::<Document>("books");
let docs = vec![
doc! { "title": "1984", "author": "George Orwell" },
doc! { "title": "Animal Farm", "author": "George Orwell" },
doc! { "title": "The Great Gatsby", "author": "F. Scott Fitzgerald" },
];
// Insert some documents into the "mydb.books" collection.
typed_collection.insert_many(docs, None)?;
Every row has its own identifier, which is called a primary key in traditional databases. PoloDB uses the _id
field of the document as the primary key. If you don't specify one, PoloDB will create one for you.
collection.insert_one(doc! {
"_id": "Orange",
"price": 300,
})?;
Remember, primary must be unique in the collection.
Query
Querying in PoloDB is also very straightforward. You can query the collection by the field of the data:
// find all
let result = collection
.find(doc! {
"author": "Liu Cixin"
})?
.collect::<Result<Vec<Document>>>()?;
// only find the first one
let result = collection.find_one(doc! {
"author": "Liu Cixin"
})?;
You can even query the field in the embedded document:
collection.insert_one(doc! {
"name": "Banana",
"price": 200,
"info": {
"description": "This is a banana",
"color": "yellow",
}
})?;
collection.insert_one(doc! {
"name": "Orange",
"price": 300,
"info": {
"description": "This is an orange",
"color": "orange",
}
})?;
// query a fruit with color yellow
let result = collection.find(doc! {
"info.color": "yellow",
})?.collect::<Result<Vec<Document>>>()?;
If you need more complex queries, you can refer to this documentation.
Update
It’s easy to update one or many rows of data in PoloDB. To update rows, you need to provide the conditions for which rows to update and specify how to update them.
let collection = db.collection::<Document>("config");
collection.update_many(doc! {
"_id": "Orange"
}, doc! {
"$set": doc! {
"price": 500,
},
})?;
If you want to update only one row in the collection, use the update_one
method.
collection.update_one(doc! {
"_id": "Orange"
}, doc! {
"$set": doc! {
"price": 500,
},
})?;
There are many ways to update a row in MongoDB. In addition to the $set
directive, you can use $inc
to increase the value of a field:
collection.update_one(doc! {
"_id": "Orange"
}, doc! {
"$inc": doc! {
"price": 1,
},
})?;
You can find more directives for updating at https://www.polodb.org/docs/curd/update.
Delete
PoloDB provides delete_one
and delete_many
methods to delete one or many rows in a database. Just provide the correct filter parameter to select the rows you want to delete:
let deleted_result = collection.delete_many(doc!{
"_id": key,
})?;
The method returns the number of rows that were deleted from the result.
Conclusion
PoloDB is a simple yet powerful database system that is still under development. It needs your input to improve. This article demonstrates its basic functions, but there are also many advanced features such as sessions and transactions. If you are interested, you can read the documentation and give it a try. I believe PoloDB would be helpful for your app.