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,
},
},
},
});
CodePudding user response:
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
CodePudding user response:
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.
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);