I have the following schema in my App:
const storySchema = new mongoose.Schema({
createdAt: { type: Date, expires: 10000 , default: Date.now },
title: {type: String},
creator: {type: Mongoose.types.ObjectId, ref: "User"},
tags: [{type: String}],
....
})
currentSchema.index({"createdAt": 1 },{ expireAfterSeconds: 10000 });
The code above adds an index
to ensure every story
document is removed after 10000
ms. This code works correctly.
However I have a user schema designed like so:
const userSchema = new mongoose.Schema({
stories: [{ type: Mongoose.Schema.Types.ObjectId, ref: "Story" }],
title: {type: String},
bio: {type: String},
....
})
When a story is automatically removed/expired
I would like to automatically remove that story from the stories
array of objectids
which is stored on the creators document. I tried adding a pre('remove')
middleware on the User model, however this isn't fired when a document expires.
To use a virtual property first remove the stories
field from your userSchema
and then update like so:
const userSchema = new mongoose.Schema({
title: {type: String},
bio: {type: String},
},{
toJSON: { virtuals: true },
toObject: { virtuals: true }
});
userSchema.virtual('stories', {
ref: 'Story',
localField: '_id',
foreignField: 'creator'
});
You will note the use of toJSON
and toObject
options set to true
. This ensures your new virtual stories
field will be sent to your front-end if using res.json()
etc.
Now you can use Model.populate()
to get all of the documents from the stories
collection where the Story.creator
field matches the User._id
and will ensure no expired documents reside in your user documents. Populating this way will only fetch stories that are live at the moment the query is made.
const user = await User.findOne({bio: 'something'}).populate('stories');
const users = await User.find().populate('stories');