A library that maps object structures to relational databases and provides interfaces for common queries and updates.
Omi is under active development and when adding a dependency you will need to add it via the git repository method like the following:
# Cargo.toml
[dependencies]
omi = { git = "https://github.com/amphitheatre-app/omi" }
Let's start with a quick preview of some of Omi's main current features, which will be updated here and in possible future special documents as they become available, so stay tuned!
use omi::prelude::*
#[entity(table = "products")]
#[derive(Entity, Queryable, Creatable, Updatable, Deletable)]
pub struct Product {
/// Auto incremented primary key
#[column(primary, auto, null)]
id: u64,
/// The title of product
#[column(length = 255, default = "")]
title: String
/// The brand of this product
#[relation(belongs_to)]
brand: Brand,
/// Has many reviews
#[relation(has_many)
reviews: Vec<Review>,
}
Using the one()
method allows you to retrieve a single record without setting
any filter conditions, which is equivalent to "SELECT * FROM products offset 0 limit 1
". Of course, you can also specify filter fields:
Product::find().one(db);
Typically, we use the all()
method to get multiple rows, which will query the
database based on the filters you submit, the equivalent SQL is SELECT * FROM products
.
Product::find().all(db);
Omi's filter()
method provides a more advanced filtering capability, where you
can simply enter a tuple, or a vector of combinations of conditions:
// SQL: SELECT * FROM products WHERE id=123
Product::find().filter(("id", 123)).all(db);
// SQL: SELECT * FROM products WHERE foo=123 AND bar=456
Product::find()
.filter([("foo", 123), ("bar", 456)])
.all(db);
Omi can also be more advanced conditional expressions to support AND
, OR
filtering, the equivalent SQL is SELECT * FROM products WHERE (title like "*abc" AND brand_id=123) OR (title like "*xyz" AND brand_id=456)
.
Product::find()
.filter(
Or(
And([("title", "*abc"), ("brand_id", 123)]),
And([("title", "*xyz"), ("brand_id", 456)]),
)
)
.all(db);
The order_by()
method takes a tuple vector to specify the field or multiple
field to be sorted and the direction.
use crate::order::Direction::Desc;
// single field
Product::find()
.filter(("id", 123))
.order_by([("id", Desc)])
.all(db);
// multiple fields
Product::find()
.filter(("id", 123))
.order_by([("id", Desc), ("id", Desc)])
.all(db);
And the group by operation is similar.
Product::find().group_by(["brand_id", "status"]).all(db);
Finally, the offset
and limit
limits are essential for query statements
Product::find().offset(0).limit(20).all(db);
Create an instance of your entity and simply call the create()
method to insert a
new record into the database:
Product::create(product).execute(db);
The first way is to make changes to the instance and then call the update()
method
to update it. Omi will automatically recognize the model of this instance and
compare the differences, saving only the changed part of the fields to the
database.
Product::update(Some(product)).execute(db);
Of course, you can also call the update()
method to update the specified fields
raw, which eliminates the need for prior data loading, reduces the number of
database reads, and, in certain cases, optimizes the processing speed of the
application.
// single field
Product::update(None)
.filter(("id", 123))
.set("title", "abc")
.execute(db);
// multiple fields
Product::update(None)
.filter(("id", 123))
.set([("title", "abc"), ("brand_id", "456")])
.execute(db);
Product::delete(product).execute(db);
You can call the include()
or exclude()
methods to include or exclude associated
objects, and by default all associated data for this model will be included.
Product::find().filter(("id", 123)).include(["reviews"]).one(db);
Product::find().filter(("id", 123)).exclude(["reviews"]).one(db);
omi::transaction::start();
omi::transaction::rollback();
omi::transaction::commit();
You can use the raw()
method for edge cases where existing mechanisms or
interfaces don't meet your needs, and it will still provide you with object
mapping support.
omi::raw::<Product>(
format!("SELECT * FROM products where id = {}", 123)
).execute(db);
If anything feels off, or if you feel that some functionality is missing, please check out the contributing page. There you will find instructions for sharing your feedback, building the tool locally, and submitting pull requests to the project.
Omi is licensed under Apache License 2.0. See LICENSE for more information.