DEV Community

Vincent Chan
Vincent Chan

Posted on

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(),
})?;
Enter fullscreen mode Exit fullscreen mode

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)?;
Enter fullscreen mode Exit fullscreen mode

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,
})?;
Enter fullscreen mode Exit fullscreen mode

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"
})?;
Enter fullscreen mode Exit fullscreen mode

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>>>()?;
Enter fullscreen mode Exit fullscreen mode

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,
    },
})?;

Enter fullscreen mode Exit fullscreen mode

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,
    },
})?;
Enter fullscreen mode Exit fullscreen mode

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,
    },
})?;
Enter fullscreen mode Exit fullscreen mode

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,
})?;
Enter fullscreen mode Exit fullscreen mode

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.

Top comments (1)

Collapse
 
cjsmocjsmo profile image
Charlie J Smotherman

Thanks for this. I have a raspberry pi project that this would be perfect for.