Минимальный воспроизводимый пример
pub struct User {
pub id: i32,
pub name: String,
pub match_id: i32,
}
pub struct Match {
pub id: i32,
pub name: String,
}
pub struct MatchWithUsers {
pub id: i32,
pub name: String,
pub users: Vec<User>,
}
fn main() {
let query_result: Vec<(Match, Option<User>)> = vec![
(
Match {
id: 1,
name: String::from("1st match"),
},
Some(User {
id: 1,
name: String::from("Jack"),
match_id: 1,
}),
),
(
Match {
id: 2,
name: String::from("2nd match"),
},
Some(User {
id: 2,
name: String::from("John"),
match_id: 2,
}),
),
(
Match {
id: 3,
name: String::from("3rd match"),
},
None,
),
];
let mut response: Vec<MatchWithUsers> = Vec::new();
for (m, u) in &query_result {
let existing_match = &response
.into_iter()
.find(|match_with_user| match_with_user.id == m.id);
match existing_match {
Some(found_match) => {
println!("Inser user into match: {}", found_match.name);
match u {
Some(mut user) => {
found_match.users.push(user);
}
None => println!("No users."),
}
}
None => {
println!("No existing match. Add to response.");
let user = u.as_ref().unwrap();
response.push(MatchWithUsers {
id: m.id,
name: m.name.clone(),
users: vec![],
});
}
}
}
println!("Response with: {}", response.len());
}
warning: unused variable: `user`
--> src/main.rs:69:21
|
69 | let user = u.as_ref().unwrap();
| ^^^^ help: consider prefixing with an underscore: `_user`
|
= note: `#[warn(unused_variables)]` on by default
warning: variable does not need to be mutable
--> src/main.rs:61:26
|
61 | Some(mut user) => {
| ----^^^^
| |
| help: remove this `mut`
|
= note: `#[warn(unused_mut)]` on by default
error[E0382]: use of moved value: `response`
--> src/main.rs:53:31
|
50 | let mut response: Vec<MatchWithUsers> = Vec::new();
| ------------ move occurs because `response` has type `std::vec::Vec<MatchWithUsers>`, which does not implement the `Copy` trait
...
53 | let existing_match = &response
| ^^^^^^^^ value moved here, in previous iteration of loop
error[E0507]: cannot move out of `u.0` which is behind a shared reference
--> src/main.rs:60:23
|
60 | match u {
| ^
61 | Some(mut user) => {
| --------
| |
| data moved here
| move occurs because `user` has type `User`, which does not implement the `Copy` trait
error[E0596]: cannot borrow `found_match.users` as mutable, as it is behind a `&` reference
--> src/main.rs:62:25
|
62 | found_match.users.push(user);
| ^^^^^^^^^^^^^^^^^ `found_match` is a `&` reference, so the data it refers to cannot be borrowed as mutable
Детская площадка
Моя проблема
У меня тестовый проект API с использованием Rocket и Diesel .
Следующий метод выполняет запрос Diesel и должен отобразить результат в ответ JSON. Это ответ всех совпадений в базе данных с их пользователями. Пользователи должны быть вложены в каждый узел Match
.
Моя попытка решения
- Я создаю вектор.
- Повторяем в результате запроса;
- Проверьте, существует ли совпадение в моем векторе если это так, добавьте информацию о пользователе (исходя из результата запроса) и добавьте ее к атрибуту users в текущем
MatchWithUser
, в противном случае просто добавьте структуру (MatchWithUsers
) к вектору.
pub fn show_all_matches2() -> Vec<MatchWithUsers> {
use schema::*;
let connection = establish_connection();
let query_result: Vec<(Match, Option<User>)> = matches::table
.left_join(users::table.on(users::match_id.eq(matches::id)))
.load(&connection)
.expect("Error loading matches");
let mut response: Vec<MatchWithUsers> = Vec::new();
for (m, u) in &query_result {
let existing_match = &response
.into_iter()
.find(|match_with_user| match_with_user.id == m.id);
match existing_match {
Some(mut found_match) => {
println!("Inser user into match: {}", found_match.name);
found_match.users.push(u.unwrap());
}
None => {
println!("No existing match. Add to response.");
let user = u.as_ref().unwrap();
response.push(MatchWithUsers {
id: m.id,
name: m.name.clone(),
players_count: m.players_count,
users: vec![User {
id: user.id,
name: user.name.clone(),
match_id: user.match_id,
}],
});
}
}
}
response
}
Структуры
use crate::schema::{matches, users};
use serde::{Deserialize, Serialize};
#[derive(Queryable, Identifiable, Associations, Serialize, Deserialize)]
#[belongs_to(Match)]
#[table_name = "users"]
pub struct User {
pub id: i32,
pub name: String,
pub match_id: i32,
}
#[derive(Queryable, Identifiable, Serialize, Deserialize)]
#[table_name = "matches"]
pub struct Match {
pub id: i32,
pub name: String,
pub players_count: i32,
}
#[derive(Serialize, Deserialize)]
pub struct MatchWithUsers {
pub id: i32,
pub name: String,
pub players_count: i32,
pub users: Vec<User>,
}
Ошибки
$ cargo run
Compiling got_board_api_v3 v0.1.0 (/Users/tauil/Projects/got/got-board-api-v3)
error[E0382]: use of moved value: `response`
--> src/lib.rs:54:31
|
51 | let mut response: Vec<MatchWithUsers> = Vec::new();
| ------------ move occurs because `response` has type `std::vec::Vec<models::MatchWithUsers>`, which does not implement the `Copy` trait
...
54 | let existing_match = &response
| ^^^^^^^^ value moved here, in previous iteration of loop
error[E0507]: cannot move out of `existing_match.0` which is behind a shared reference
--> src/lib.rs:58:15
|
58 | match existing_match {
| ^^^^^^^^^^^^^^
59 | Some(mut found_match) => {
| ---------------
| |
| data moved here
| move occurs because `found_match` has type `models::MatchWithUsers`, which does not implement the `Copy` trait
error[E0507]: cannot move out of `*u` which is behind a shared reference
--> src/lib.rs:61:40
|
61 | found_match.users.push(u.unwrap());
| ^
| |
| move occurs because `*u` has type `std::option::Option<models::User>`, which does not implement the `Copy` trait
| help: consider borrowing the `Option`'s content: `u.as_ref()`
Результат запроса в клиенте Postgres:
select * from matches left join users on matches.id = users.match_id;
id | name | players_count | id | name | match_id
----+---------------------+---------------+----+-----------+----------
1 | My first match | 3 | 1 | Rafael | 1
1 | My first match | 3 | 2 | Leandro | 1
1 | My first match | 3 | 3 | Vagner | 1
2 | Just a second match | 4 | 4 | Vagner | 2
2 | Just a second match | 4 | 5 | Leandro | 2
2 | Just a second match | 4 | 6 | Rafael | 2
2 | Just a second match | 4 | 7 | Wanderson | 2
3 | Amazing match | 6 | | |
(8 rows)