Skip to content

find_one returns None when searched with enum variants with unknown fields #1545

@sumit-modak

Description

@sumit-modak

Versions/Environment

  1. What version of Rust are you using? 1.90
  2. What operating system are you using? NixOS Unstable
  3. What versions of the driver and its dependencies are you using? (Run
    cargo pkgid mongodb & cargo pkgid bson) registry+https://github.com/rust-lang/crates.io-index#[email protected] registry+https://github.com/rust-lang/crates.io-index#[email protected]
  4. What version of MongoDB are you using? cloud.mongodb.com
  5. What is your MongoDB topology (standalone, replica set, sharded cluster, serverless)? I guess sharded cluster

Describe the bug

I am using a enum ApplicationStatus for storing the current state of the Applicant. ApplicationStatus is internally tagged. I tried searching the applicants collection with different queries none of them worked only the first one worked (see below function).

The same queries ran on mongodb cloud without any issues

#[derive(serde::Deserialize, serde::Serialize)]
pub struct Applicant {
    pub display_name: Option<String>,
    pub email: String,
    pub birth_date: Option<mongodb::bson::DateTime>,
    pub password: Option<String>,
    pub icon: Option<String>,
    pub phone: Option<String>,
    pub status: ApplicationStatus,
}

#[derive(serde::Deserialize, serde::Serialize, PartialEq, Debug, Clone)]
#[serde(tag = "tag", content = "value")]
pub enum ApplicationStatus {
    Created(String), // OTP
    EmailVerified,
    PasswordSet,
    OidcVerified,
    Recovering(String),                               // HEX HASH
    UpdatingEmail { old_email: String, otp: String }, // OTP
    UpdatingPhone { old_phone: String, otp: String }, // OTP
}

impl crate::Db {
    pub async fn verify_applicant_email(
        self: Arc<Self>,
        email: &str,
        otp: &str,
    ) -> Result<(), AppError> {
        let filter = 
           doc! {"email": email, "status": {"tag": "Created", "value": otp}}; // this query works
        // doc! {"email": email, "status": {"tag": "Created", "value": {"$exists": true}}}; // this doesn't
        // doc! {"email": email, "status": {"tag": "Created"}}; // neither this one
        // doc! {"email": email, "status.tag": "Created"}; // nor this one
        let applicant = match self.applicants.find_one(filter.clone()).await {
            Ok(Some(v)) => v,
            Ok(None) => return Err(AppError::UserNotFound),
            Err(e) => {
                tracing::error!("{e:?}");
                return Err(AppError::ServerError);
            }
        };
        if let ApplicationStatus::Created(db_otp) = applicant.status
            && db_otp == otp
        {
            let status_bson = bson::to_bson(&ApplicationStatus::EmailVerified).unwrap();
            let update = doc! {"$set": {"status": status_bson }};
            match self.applicants.update_one(filter, update).await {
                Ok(_) => {
                    tracing::info!("[Email Verified] Email: {email}");
                    Ok(())
                }
                Err(e) => {
                    tracing::error!("{e:?}");
                    Err(AppError::ServerError)
                }
            }
        } else {
            Err(AppError::InvalidOTP)
        }
    }
}

BE SPECIFIC:

  • What is the expected behavior and what is actually happening? MongoDB should give out a document, but it returns None
  • Do you have any particular output that demonstrates this problem?
  • Do you have any ideas on why this may be happening that could give us a
    clue in the right direction?
  • Did this issue arise out of nowhere, or after an update (of the driver,
    server, and/or Rust)?
  • Are there multiple ways of triggering this bug (perhaps more than one
    function produce a crash)? No
  • If you know how to reproduce this bug, please include a code snippet here:

To Reproduce
Steps to reproduce the behavior:

  1. Run the code
  2. Insert a document
  3. Find or try to update the document with the types specified above

Metadata

Metadata

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions