skip to Main Content

I’m trying to access a database with the following difficult schema and want to update the file_name value if it exists, or create a new object with the file_name if it does not. As I have searched, the option { upsert: true, new: true, setDefaultsOnInsert: true }; will update do the second bit, but the problem is how do you access the file_name key nested deep within.

export type _ID = string;
export interface FileSchema {
    [_id: _ID]: {
        file_name: string;
        creation_date: Date;
        isPublished: boolean;
        content: string;
    };
}
export interface AccountSchema {
  ...
    files: FileSchema;
}
const accountSchema = new Schema<AccountSchema>({
  ...
    files: {
        type: Map,
        unique: true,
        of: {
            file_name: {
                type: String,
                required: true,
                minlength: 4,
                maxlength: 60,
                unique: true,
            },
            creation_date: {
                type: Date,
                required: true,
            },
            isPublished: {
                type: Boolean,
                required: true,
            },
            content: {
                type: String,
                required: true,
            },
        },
    },
});

2

Answers


  1. Chosen as BEST ANSWER

    I've searched a bit, and have come up with the solution below, although not pretty due to multiple queries. For nested objects with a dynamic key, you must use codes like [files.${file_id}.file_name] (with ``) to access the object within.

    1. Reference 1
    2. Reference 2

    const accountSchema = new Schema<AccountSchema>({
    ... 
      files: {
          type: Schema.Types.Map,
          unique: true,
          of: Object,
      },
    })

    // checks if file exists, if exist then update file_name
    const files: FileSchema | null = await DB_ACCOUNT.findOneAndUpdate(
        {
            _id,
            username,
            [`files.${file_id}`]: { $exists: true },
        },
        {
            $set: {
                [`files.${file_id}.file_name`]: file_name,
            },
        },
        { new: true, upsert: false, useFindAndModify: false }
    );
    const fn = genObjectId().toString();
    // if file does not exist, then create a new file
    const x = await DB_ACCOUNT.findOneAndUpdate(
        {
            _id,
            username,
        },
        {
            $set: {
                [`files.${fn}`]: {
                    file_name,
                    creation_date: new Date(),
                    isPublished: false,
                    content: "",
                },
            },
        },
        { new: true, upsert: true }
    )
    console.log("X: ", x);


  2. Not familiar with Mongoose but you may be missing dot notation to access nested fields, look at
    https://www.mongodb.com/docs/manual/tutorial/query-embedded-documents/#specify-equality-match-on-a-nested-field

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search