I am trying to perform inner join on two vectors in rust but not sure how to achieve this.
In short, I am looking for employees with their department name.
If anybody is familiar with C# LINQ here, then I am trying to achieve something like below in rust.
Considering same model as specified below in model.rs
from e in employees
join d in department
on e.dept_id equals d.dept_id
select new
{
DeptName= d.dept_name,
Name = e.name
};
Here is my rust language code:
models.rs
use bigdecimal::BigDecimal;
use chrono::{NaiveDateTime, Utc};
pub struct Department {
pub dept_id: i32,
pub dept_name: Option<String>,
pub created_on: Option<NaiveDateTime>,
pub created_by: Option<String>,
pub modified_on: Option<NaiveDateTime>,
pub modified_by: Option<String>,
pub is_active: Option<bool>,
}
impl Department {
pub fn get_departments() -> Vec<Department> {
vec![
Department {
dept_id: 101,
dept_name: Option::from("Software".to_string()),
created_on: Option::from(Utc::now().naive_utc()),
created_by: Option::from("Jadon".to_string()),
modified_on: None,
modified_by: None,
is_active: Option::from(true),
},
Department {
dept_id: 102,
dept_name: Option::from("Hr".to_string()),
created_on: Option::from(Utc::now().naive_utc()),
created_by: Option::from("Jadon".to_string()),
modified_on: None,
modified_by: None,
is_active: Option::from(true),
},
Department {
dept_id: 103,
dept_name: Option::from("Hr".to_string()),
created_on: Option::from(Utc::now().naive_utc()),
created_by: Option::from("Jadon".to_string()),
modified_on: None,
modified_by: None,
is_active: Option::from(true),
},
]
}
}
pub struct Employee {
pub employee_id: i32,
pub name: Option<String>,
pub age: Option<i32>,
pub address: Option<String>,
pub email: Option<String>,
pub dept_id: i32,
pub salary: Option<BigDecimal>,
pub created_on: Option<NaiveDateTime>,
pub created_by: Option<String>,
pub modified_on: Option<NaiveDateTime>,
pub modified_by: Option<String>,
pub is_active: Option<bool>,
}
impl Employee {
pub fn get_employees() -> Vec<Employee> {
vec![
Employee {
employee_id: 1001,
name: Option::from("Marten Babel".to_string()),
age: Option::from(25),
address: Option::from("Netherland".to_string()),
email: Option::from("somemail@gmail.com".to_string()),
dept_id: 101,
salary: Option::from(BigDecimal::from(50000.00)),
created_on: Option::from(Utc::now().naive_utc()),
created_by: Option::from("Tom".to_string()),
modified_on: None,
modified_by: None,
is_active: Option::from(true),
},
Employee {
employee_id: 1002,
name: Option::from("Jack Sancho".to_string()),
age: Option::from(22),
address: Option::from("England".to_string()),
email: Option::from("jacksemail@gmail.com".to_string()),
dept_id: 102,
salary: Option::from(BigDecimal::from(80000.00)),
created_on: Option::from(Utc::now().naive_utc()),
created_by: Option::from("Tom".to_string()),
modified_on: None,
modified_by: None,
is_active: Option::from(true),
},
Employee {
employee_id: 1003,
name: Option::from("Phil Foden".to_string()),
age: Option::from(29),
address: Option::from("England".to_string()),
email: Option::from("philsemail@gmail.com".to_string()),
dept_id: 101,
salary: Option::from(BigDecimal::from(80000.00)),
created_on: Option::from(Utc::now().naive_utc()),
created_by: Option::from("Tom".to_string()),
modified_on: None,
modified_by: None,
is_active: Option::from(true),
},
]
}
}
main.rs
fn main() {
let department: Vec<Department> = Department::get_departments();
for dept in department {
println!(
"Dept Id: {} and Dept Name: {}",
dept.dept_id,
dept.dept_name.unwrap_or_default()
);
}
let employee: Vec<Employee> = Employee::get_employees();
for emp in employee {
println!(
"Name is: {} and age is : {}",
emp.name.unwrap_or_default(),
emp.age.unwrap_or_default()
)
}
}
Here "dept_id" will be acting as a foreign key.
The code in main.rs is working fine. I am getting departments and employees but how can I perform join on these two vectors.
Note: As of now I am not using diesel orm. Only looking to perform join on these vectors.
Is it possible in rust ?
Thanks
If you just want to get pairs of &str
for the names of the departments and the employees, you can use an iterator chain like so:
let department: Vec<Department> = Department::get_departments();
let employee: Vec<Employee> = Employee::get_employees();
let dept_employee_names = department.iter().flat_map(|d| {
let dept_id = d.dept_id;
let dept_name = &d.dept_name;
employee
.iter()
.filter(move |e| e.dept_id == dept_id)
.map(move |e| {
(
dept_name.as_deref().unwrap_or_default(),
e.name.as_deref().unwrap_or_default(),
)
})
});
for (dept, emp) in dept_employee_names {
println!("dept = {}, emp = {}", dept, emp);
}
Note that this has to search through all of the employees for each department, but that is really a limitation of using vectors. You can probably make this more efficient by changing the data structures.