Как получить Option‹T› вместо Option‹Vec‹T›› из запроса Diesel, который возвращает только 1 или 0 записей?

Я запрашиваю существующие записи в таблице с именем messages; затем этот запрос используется как часть функции «найти или создать»:

fn find_msg_by_uuid<'a>(conn: &PgConnection, msg_uuid: &Uuid) -> Option<Vec<Message>> {
    use schema::messages::dsl::*;
    use diesel::OptionalExtension;

    messages.filter(uuid.eq(msg_uuid))
        .limit(1)
        .load::<Message>(conn)
        .optional().unwrap()
}

Я сделал это необязательным, поскольку и поиск записи, и ее отсутствие являются допустимыми результатами в этом сценарии, поэтому в результате этот запрос может вернуть Vec с одним Message или пустым Vec, поэтому я всегда заканчиваю тем, что проверяю, является ли Vec пустой или не использующий такой код:

let extant_messages = find_msg_by_uuid(conn, message_uuid);

if !extant_messages.unwrap().is_empty() { ... }

а затем, если он не пуст, принимая первое Message в Vec как мое найденное сообщение, используя код вроде

let found_message = find_msg_by_uuid(conn, message_uuid).unwrap()[0];

Я всегда беру первый элемент в Vec, поскольку записи уникальны, поэтому запрос будет возвращать только 1 или 0 записей.

Это кажется мне запутанным и, кажется, требует слишком много шагов, я чувствую, что если есть запись для запроса, то она должна возвращать Option<Message>, а не Option<Vec<Message>> или None, если нет записи, соответствующей запросу.


person dch    schedule 19.09.2017    source источник
comment
вы, вероятно, захотите использовать в первую очередь   -  person user25064    schedule 19.09.2017


Ответы (1)


Как упоминалось в комментариях, используйте first:

Попытки загрузить одну запись. Возвращает Ok(record), если найдено, и Err(NotFound), если результаты не возвращаются. Если запрос действительно является необязательным, вы можете вызвать .optional() в результате этого, чтобы получить Result<Option<U>>.

fn find_msg_by_uuid<'a>(conn: &PgConnection, msg_uuid: &Uuid) -> Option<Message> {
    use schema::messages::dsl::*;
    use diesel::OptionalExtension;

    messages
        .filter(uuid.eq(msg_uuid))
        .first(conn)
        .optional()
        .unwrap()
}
person Shepmaster    schedule 19.09.2017