Omi - Object Mapping Intelligently

Overview

Omi - Object Mapping Intelligently

A library that maps object structures to relational databases and provides interfaces for common queries and updates.

License GitHub contributors GitHub issues

Install

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" }

Getting Started

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!

Entity definition

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>,
}

Querying

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

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);

Update

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);

Delete

Product::delete(product).execute(db);

Relations

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);

Transaction

omi::transaction::start();
omi::transaction::rollback();
omi::transaction::commit();

Raw queries

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);

Contributing

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.

License

Omi is licensed under Apache License 2.0. See LICENSE for more information.

You might also like...
Rusty Object Notation

Rusty Object Notation RON is a simple readable data serialization format that looks similar to Rust syntax. It's designed to support all of Serde's da

Object Pool LockFree in Rust

Lock Free Object Pool A thread-safe object pool collection with automatic return. Some implementations are lockfree : LinearObjectPool SpinLockObjectP

C++ `std::unique_ptr` that represents each object as an NFT on the Ethereum blockchain
C++ `std::unique_ptr` that represents each object as an NFT on the Ethereum blockchain

C++ `std::unique_ptr` that represents each object as an NFT on the Ethereum blockchain

Educational Rust implemenation of Auction Sniper from Growing Object-Oriented Software, Guided By Tests

Auction Sniper Educational Rust not-OOP implemenation of Auction Sniper from "Growing Object-Oriented Software, Guided By Tests" book More about it in

It is a backup tool that creates backups and stores them on an object storage
It is a backup tool that creates backups and stores them on an object storage

Hold My Backup It is a backup tool that creates backups and stores them on an object storage. By default it uses minio but you can use AWS: S3 as well

An object-relational in-memory cache, supports queries with an SQL-like query language.

qlcache An object-relational in-memory cache, supports queries with an SQL-like query language. Warning This is a rather low-level library, and only p

Garage is a lightweight S3-compatible distributed object store

Garage [ Website and documentation | Binary releases | Git repository | Matrix channel ] Garage is a lightweight S3-compatible distributed object stor

Merge together and efficiently time-sort compressed .pcap files stored in AWS S3 object storage (or locally) to stdout for pipelined processing.

Merge together and efficiently time-sort compressed .pcap files stored in AWS S3 object storage (or locally) to stdout for pipelined processing. High performance and parallel implementation for 10 Gbps playback throughput with large numbers of files (~4k).

CBOR: Concise Binary Object Representation

CBOR 0x(4+4)9 0x49 “The Concise Binary Object Representation (CBOR) is a data format whose design goals include the possibility of extremely small cod

My solutions for the 2021 edition of the Advent of Code, using Rust and SOM (Simple Object Machine)

Advent of Code 2021 These are my solutions for the 2021 edition of the Advent of Code. The solutions are all implemented using both Rust and SOM (Simp

Eon-rs - A reference parser for EON (Extensible Object Notation)

eon-rs eon-rs is a Rust library for parsing EON. Installation Add eon-rs = "1.0.0" to your Cargo.toml file. Usage use eon_rs; // Read EON from file l

Qoo - Query Object Oriented. Pronunciation is Kuu.

qoo Query Object Oriented. Pronunciation is Kuu. demo use qoo::base::*; use qoo::select::*; use qoo::insert::*; use qoo::update::*; use qoo::delete::*

Parser for Object files define the geometry and other properties for objects in Wavefront's Advanced Visualizer.

format of the Rust library load locad blender obj file to Rust NDArray. cargo run test\t10k-images.idx3-ubyte A png file will be generated for the fi

Parses .off (Object File Format) files. This implementation follows this spec from the Princeton Shape Benchmark.

off-rs - A simple .off file parser Parses .off (Object File Format) files. This implementation follows this spec from the Princeton Shape Benchmark. S

Sorock is an experimental
Sorock is an experimental "so rocking" scale-out distributed object storage

Sorock is an experimental "so rocking" scale-out distributed object storage

garbage-collecting on-disk object store, supporting higher level KV stores and databases.

marble Garbage-collecting disk-based object-store. See examples/kv.rs for a minimal key-value store built on top of this. Supports 4 methods: read: de

Ecstasy - a subjective experience of total involvement of the subject, with an object of their awareness.

Ecstasy (from Ancient Greek ἔκστασις ékstasis, meaning 'outside of oneself') is a subjective experience of total involvement of the subject, with an object of their awareness. In classical Greek literature it refers to removal of the mind or body "from its normal place of function."

Machine learning framework for building object trackers and similarity search engines

Similari Similari is a framework that helps build sophisticated tracking systems. The most frequently met operations that can be efficiently implement

Object Notation Programming Language?
Object Notation Programming Language?

You may have questions ONLang - Object Notation Language (jsON) VSCode extension - OnLang 1. God, what the f**** is this ONLang is an experimental, es

Comments
  • Added some descriptions in README.md

    Added some descriptions in README.md

    1. Added.idea configuration to the.gitignore file. jetbrains products submit the.idea directory by default when you use the git add . command
    2. Added some descriptions about the configuration environment.
    opened by azhsmesos 0
  • MySQL, PostgresSQL and Sqlite database drivers

    MySQL, PostgresSQL and Sqlite database drivers

    omi::Database serves as the external interface to provide database services for upper-level queries, while internally it does the real database connection and execution work through a concrete driver.

    Currently, I have opened the module of omi::driver and just added an empty implementation skeleton. Community members are welcome to claim this feature and help us achieve real data accessibility.

    Attachment: interface definition of omi::driver: https://github.com/amphitheatre-app/omi/commit/1860e4e621e48759ebc30c7f1c08deaf42383999

    enhancement help wanted 
    opened by wangeguo 1
  • Implement start, rollback, and commit functions for simple transaction processing

    Implement start, rollback, and commit functions for simple transaction processing

    Functions:

    omi::transaction::start(); omi::transaction::rollback(); omi::transaction::commit();

    Source file:

    https://github.com/amphitheatre-app/omi/blob/master/src/transaction.rs

    Intro

    To start a new transaction in MySQL, you can use the START TRANSACTION statement. For example:

    START TRANSACTION;
    

    This statement will start a new transaction and allow you to execute multiple SQL statements as a single unit of work. When you are ready to commit the transaction, you can use the COMMIT statement. For example:

    COMMIT;
    

    Alternatively, if you want to roll back the transaction and discard any changes made by the SQL statements, you can use the ROLLBACK statement. For example:

    ROLLBACK;
    

    It's important to note that starting a transaction will not automatically commit or roll back the changes made by the SQL statements. You must explicitly issue a COMMIT or ROLLBACK statement to either save or discard the changes.

    Demo

    // transaction.rs
    use sql_query_builder as sql;
    
    /// Start a transaction
    pub fn start() {
        let query = sql::Select::new().raw("START TRANSACTION").as_string();
       db::execute(sql);
    }
    
    See [sql_query_builder#raw-queries](https://github.com/belchior/sql_query_builder#raw-queries) for more information.
    
    good first issue help wanted 
    opened by wangeguo 2
  • Help Omi do code static quality analysis

    Help Omi do code static quality analysis

    Requirements:

    • Learn and master basic Sonaqube;
    • Learn and master basic Github Actions;
    • Configure Github Actions for Omi, and create a Sonaqube Step in it;
    • Add Hooks checks before Commit and Pull Request, and then display the Sonaqube analysis results on the PR list (see other projects).

    Thanks!

    help wanted 
    opened by wangeguo 0
Owner
Amphitheatre
Instantly spin up fresh, automated dev environments in the cloud and start developing within seconds.
Amphitheatre
Educational Rust implemenation of Auction Sniper from Growing Object-Oriented Software, Guided By Tests

Auction Sniper Educational Rust not-OOP implemenation of Auction Sniper from "Growing Object-Oriented Software, Guided By Tests" book More about it in

Dawid Ciężarkiewicz 23 Nov 11, 2022
Merge multiple Juniper object definitions into a single object type.

juniper-compose Merge multiple Juniper object definitions into a single object type. crates.io | docs | github Motivation You are building a GraphQL s

Kit Isaev 3 Aug 5, 2022
A utility for mapping events from Linux event devices.

What is evsieve? Evsieve (from "event sieve") is a low-level utility that can read events from Linux event devices (evdev) and write them to virtual e

Kars Mulder 116 Jan 2, 2023
LevelDB is a fast key-value storage library written at Google that provides an ordered mapping from string keys to string values.

LevelDB is a fast key-value storage library written at Google that provides an ordered mapping from string keys to string values. Authors: Sanjay Ghem

Google 31.5k Jan 1, 2023
bevy-hikari is an implementation of voxel cone tracing global illumination with anisotropic mip-mapping in Bevy

Bevy Voxel Cone Tracing bevy-hikari is an implementation of voxel cone tracing global illumination with anisotropic mip-mapping in Bevy. Bevy Version

研究社交 208 Dec 27, 2022
Functions for mapping plaintexts to a u64 while preserving sort order

ore_encoding.rs This is a companion package to ore.rs that can generate and manipulate u64 plaintexts before they are encrypted by ore.rs. Being able

CipherStash 2 Dec 14, 2022
Parallax mapping shaders (relief and POM) for the bevy game engine

Bevy parallax mapping parallax mapping is a graphical effect adding the impression of depth to simple 2d textures by moving the texture's pixel around

Nicola Papale 10 Dec 28, 2022
A vcf parser that use memory mapping to get high performance.

biommap An efficient bioinformatics file parser based on memory mapping of file. WARNING: biommap work only on uncompressed seekable file biommap is t

Pierre Marijon 2 Dec 15, 2022
Executable memory allocator with support for dual mapping and W^X protection

jit-allocator A simple memory allocator for executable code. Use JitAllocator type to allocate/release memory and virtual_memory module functions to e

playX 5 Jul 5, 2023
A collection of mapping suites and useful algorithms, implemented in pure Rust

Unstable API Note that this crate is in early development, breaking API changes are to be expected. Usage Add this to your Cargo.toml: [dependencies]

Emily Matheys 7 Aug 31, 2023