ungroup
rel.ungroup([:attr])rel.ungroup([:attr1, :attr2])rel.ungroup('attr')Problem
Section titled “Problem”Flatten a relation-valued attribute back into regular tuples.
Example: I have suppliers with nested supplies, and I want to flatten them back into individual rows.
Description
Section titled “Description”The ungroup operator is the inverse of group. It takes a relation that has a relation-valued attribute (RVA) and expands it, creating one tuple for each combination of the outer tuple and the tuples in the nested relation.
If the nested relation is empty, the outer tuple is removed from the result (similar to an inner join).
Multiple attributes can be ungrouped in a single operation by passing an array of attribute names.
The attribute name to ungroup is passed as a string.
Requirements
Section titled “Requirements”The specified attributes must be relation-valued attributes in the input relation.
Examples
Section titled “Examples”Basic ungroup
Section titled “Basic ungroup”Starting with a grouped relation:
# First, create a grouped relationgrouped = supplies.group([:pid, :qty], :supplied_parts)grouped.to_a
=>[{:sid=>"S1", :supplied_parts=>#<Bmg::Relation [{:pid=>"P1", :qty=>300}, {:pid=>"P2", :qty=>200}, ...]>}, {:sid=>"S2", :supplied_parts=>#<Bmg::Relation [{:pid=>"P1", :qty=>300}, {:pid=>"P2", :qty=>400}]>}, {:sid=>"S3", :supplied_parts=>#<Bmg::Relation [{:pid=>"P2", :qty=>200}]>}, {:sid=>"S4", :supplied_parts=>#<Bmg::Relation [{:pid=>"P2", :qty=>200}, ...]>}]
# Now ungroup to flatten backgrouped.ungroup([:supplied_parts]).to_a
=>[{:sid=>"S1", :pid=>"P1", :qty=>300}, {:sid=>"S1", :pid=>"P2", :qty=>200}, {:sid=>"S1", :pid=>"P3", :qty=>400}, {:sid=>"S1", :pid=>"P4", :qty=>200}, {:sid=>"S1", :pid=>"P5", :qty=>100}, {:sid=>"S1", :pid=>"P6", :qty=>100}, {:sid=>"S2", :pid=>"P1", :qty=>300}, {:sid=>"S2", :pid=>"P2", :qty=>400}, {:sid=>"S3", :pid=>"P2", :qty=>200}, {:sid=>"S4", :pid=>"P2", :qty=>200}, {:sid=>"S4", :pid=>"P4", :qty=>300}, {:sid=>"S4", :pid=>"P5", :qty=>400}]Starting with a grouped relation:
// First, create a grouped relationconst grouped = supplies.group(['pid', 'qty'], 'supplied_parts')
// Now ungroup to flatten backgrouped.ungroup('supplied_parts').toArray()
// =>// [{ sid: "S1", pid: "P1", qty: 300 },// { sid: "S1", pid: "P2", qty: 200 },// { sid: "S1", pid: "P3", qty: 400 },// { sid: "S1", pid: "P4", qty: 200 },// { sid: "S1", pid: "P5", qty: 100 },// { sid: "S1", pid: "P6", qty: 100 },// { sid: "S2", pid: "P1", qty: 300 },// { sid: "S2", pid: "P2", qty: 400 },// { sid: "S3", pid: "P2", qty: 200 },// { sid: "S4", pid: "P2", qty: 200 },// { sid: "S4", pid: "P4", qty: 300 },// { sid: "S4", pid: "P5", qty: 400 }]Relationship with group
Section titled “Relationship with group”ungroup and group are inverse operations:
# Starting with suppliessupplies.to_a=> [{:sid=>"S1", :pid=>"P1", :qty=>300}, ...]
# Group by sidgrouped = supplies.group([:pid, :qty], :items)
# Ungroup back - returns to originalgrouped.ungroup([:items]).to_a=> [{:sid=>"S1", :pid=>"P1", :qty=>300}, ...] # Same as original// Starting with suppliessupplies.toArray()// => [{ sid: "S1", pid: "P1", qty: 300 }, ...]
// Group by sidconst grouped = supplies.group(['pid', 'qty'], 'items')
// Ungroup back - returns to originalgrouped.ungroup('items').toArray()// => [{ sid: "S1", pid: "P1", qty: 300 }, ...] // Same as original