A NoSQL embedded database for you Rust app
Tags: rust, database
Published: 2023-05-24 12:46:45

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](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:

```rust
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:

```rust
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.

```rust
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:

```rust
// 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:

```rust
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](https://www.polodb.org/docs/curd/query).

# 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.

```rust
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.

```rust
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:

```rust
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](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:

```rust
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.