How to return a single owned record with Diesel?

Viewed 35

Actually I'm returing a cloned struct

pub fn matrix_first_or_create(&self, schema: String, symbol: String) -> RewardMatrix {
    ....

    let rewards = reward_matrix
        .filter(state.eq(schema.clone()))
        .filter(turn_symbol.eq(symbol.clone()))
        .limit(1)
        .load::<RewardMatrix>(&self.connection)
        .expect("Error loading posts");

    if rewards.len() > 0 {
        return rewards.get(0).unwrap().clone();
    }

    ....
}

Is this the right way to handle a result in Diesel? Can I "extract" and own the first and only result from this query?

2 Answers

What you need here is the .first() method of the RunQueryDsl trait.

Here is an example of how it works:

let reward: RewardMatrix = reward_matrix
    .filter(state.eq(schema.clone()))
    .filter(turn_symbol.eq(symbol.clone()))
    .first(&self.connection)?;

But if your query may not return that row, it’s also good to use the .optional() method of QueryResult:

let reward: Option<RewardMatrix> = reward_matrix
    .filter(state.eq(schema.clone()))
    .filter(turn_symbol.eq(symbol.clone()))
    .first(&self.connection)
    .optional()?;

load returns a simple owned Vec<RewardMatrix>, so any solution for getting an owned element from a Vec works here:

if let Some(reward) = rewards.into_iter().next() {
    return reward;
}

but Diesel also provides better-suited alternatives like get_result and first that don’t involve Vec at all (combine with optional as recommended in the documentation):

let reward = reward_matrix
    .filter(state.eq(&schema))
    .filter(turn_symbol.eq(&symbol))
    .first::<RewardMatrix>(&self.connection)
    .optional()
    .expect("Error loading posts");

if let Some(reward) = reward {
    return reward;
}
Related