pub trait GroupedBy<'a, Parent>: IntoIterator + Sized {
// Required method
fn grouped_by(self, parents: &'a [Parent]) -> Vec<Vec<Self::Item>>;
// Provided method
fn try_grouped_by(
self,
parents: &'a [Parent],
) -> Result<Vec<Vec<Self::Item>>, TryGroupedByError<Self::Item>> { ... }
}
Expand description
The grouped_by
function groups records by their parent.
grouped_by
is called on a Vec<Child>
with a &[Parent]
.
The return value will be Vec<Vec<Child>>
indexed to match their parent.
Or to put it another way, the returned data can be passed to zip
,
and it will be combined with its parent.
This function does not generate a GROUP BY
SQL statement,
as it operates on data structures already loaded from the database
Child refers to the “many” part of a “one to many” relationship. It “belongs to” its parent Parent refers to the “one” part of a “one to many” relationship and can “have many” children. The child always has a foreign key, which refers to its parent’s primary key. In the following relationship, User has many Posts, so User is the parent and Posts are children.
§Example
let users = users::table.load::<User>(connection)?;
let posts = Post::belonging_to(&users)
.load::<Post>(connection)?
.grouped_by(&users);
let data = users.into_iter().zip(posts).collect::<Vec<_>>();
let expected_data = vec![
(
User { id: 1, name: "Sean".into() },
vec![
Post { id: 1, user_id: 1, title: "My first post".into() },
Post { id: 2, user_id: 1, title: "About Rust".into() },
],
),
(
User { id: 2, name: "Tess".into() },
vec![
Post { id: 3, user_id: 2, title: "My first post too".into() },
],
),
];
assert_eq!(expected_data, data);
See the module documentation for more examples
Required Methods§
Provided Methods§
Sourcefn try_grouped_by(
self,
parents: &'a [Parent],
) -> Result<Vec<Vec<Self::Item>>, TryGroupedByError<Self::Item>>
fn try_grouped_by( self, parents: &'a [Parent], ) -> Result<Vec<Vec<Self::Item>>, TryGroupedByError<Self::Item>>
A fallible alternative to GroupedBy::grouped_by
.
If any child record could not be grouped,
either because of a NULL
foreign key,
or a parent record with a matching key could not be found,
this function should return Err
,
with all successfully grouped records, as well as any ungrouped records.
§Errors
If a parent record could not be found for any of the child records,
this function should return the TryGroupedByError
.
Every supplied record should be contained in the returned error,
either in the grouped
field, if it was successfully grouped,
or the ungrouped
field, if it was not possible to associate
with a parent record.
§Examples
let users = users::table.load::<User>(connection)?;
let mut posts = Post::belonging_to(&users)
.load::<Post>(connection)?;
posts.push(
Post { id: 9, user_id: 42, title: "A post returned from another query".into() }
);
let TryGroupedByError { grouped, ungrouped, .. } = posts.try_grouped_by(&users).unwrap_err();
let grouped_data = users.into_iter().zip(grouped).collect::<Vec<_>>();
let expected_grouped_data = vec![
(
User { id: 1, name: "Sean".into() },
vec![
Post { id: 1, user_id: 1, title: "My first post".into() },
Post { id: 2, user_id: 1, title: "About Rust".into() },
],
),
(
User { id: 2, name: "Tess".into() },
vec![
Post { id: 3, user_id: 2, title: "My first post too".into() },
],
),
];
let expected_ungrouped_data = vec![
Post { id: 9, user_id: 42, title: "A post returned from another query".into() }
];
assert_eq!(expected_grouped_data, grouped_data);
assert_eq!(expected_ungrouped_data, ungrouped);
Dyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.