Skip to content

B⋈G

Relational Algebra for Modern Times

What does it look like?

# List the total number of purchases, excluding samples,
# for each product in the cheeze category
purchases
.restrict(Predicate.neq(:product_type, 'sample'))
.join(products, :product_id => :id)
.restrict(Predicate.eq(:category, 'cheeze'))
.project([:product_id, :quantity])
.summarize([:product_id], :quantity => :sum)

Keep scrolling for more examples!

What is it good for?

A solid foundation

Bmg stays faithful to the mathematical foundations of relational databases. Everything is a relation and operations can always be chained.

Works with any data

Query, transform, and combine data from SQL databases, CSV files, spreadsheets, Redis and more.

Unlimited composability

It’s trivial to extract and compose operations on relations in Bmg.

Fits in any project

You can use Bmg in any Ruby codebase, by itself or alongside ActiveRecord or any other database wrapper.

Think relations, get SQL

suppliers
.restrict(Predicate.eq(:city, "Paris"))
.project([:sid])
.join(supplies, [:sid])
.join(parts, [:pid])
.project([:name, :weight, :qty])

SELECT DISTINCT `t2`.`qty`, `t3`.`name`, `t3`.`weight`
FROM `suppliers` AS 't1'
INNER JOIN `supplies` AS 't2'
ON (`t1`.`sid` = `t2`.`sid`)
INNER JOIN `parts` AS 't3'
ON (`t2`.`pid` = `t3`.`pid`)
WHERE (`t1`.`city` = 'Paris')

suppliers
.not_matching(supplies, [:sid])

SELECT `t1`.`sid`, `t1`.`name`, `t1`.`status`, `t1`.`city`
FROM `suppliers` AS 't1'
WHERE NOT (
EXISTS (
SELECT * FROM `supplies` AS 't2'
WHERE (`t1`.`sid` = `t2`.`sid`)
)
)

suppliers
.project([:city])
.union(
parts.project([:city])
)

SELECT DISTINCT `t1`.`city`
FROM `suppliers` AS 't1'
UNION
SELECT DISTINCT `t1`.`city`
FROM `parts` AS 't1'
Created with ♥️ byEnspirit logoEnspirit logo