I have a document that has an expiration set for 2 minutes.
const docSchema = new mongoose.Schema({
createdAt: { type: Date, default: Date.now },
expireAt: { type: Date, default: Date.now, index: { expires: "2m" } },
});
const Doc = mongoose.model("Doc", docSchema);
When a Doc is created (ie. const doc = await Doc.create({});), I would expect it to have the expiration set. However, sometimes it's setting- but sometimes it's not.
I check if there's an expiration on the Doc by running db.docs.getIndexes() in a Mongo shell. The result will either show the expiration information:
[
...{// some other object},
// expiration info--->
{
"v" : 2,
"key" : {
"expireAt" : 1
},
"name" : "expireAt_1",
"ns" : "expireDocument.docs",
"expireAfterSeconds" : 120,
"background" : true
}
]
Or it will leave it out. I'm guessing it leaves it out when it didn't apply the expiration to the documents.
It seems sort of random when it gets set and when it doesn't. However, I was able to figure out a consistent situation where it is set and where it isn't so the problem can be recreated. Though, I have no clue what separates these situations besides the order they are in.
To recreate:
- Download the small repo here. You can also see the
server.jscode below. - Open the folder in VScode.
- CTR+` to open terminal. Run
npm i - Click the debugger icon. At the top left play
Expire Documentdebugger. - After the script creates a
Docthe debugger pauses online 15. While paused, open a new terminal. - Run
mongoand thenuse expireDocumentto navigate to the correct database. - Run
db.docs.getIndexes()to see the indexes. You will see the second object contains info about the expire information for `docs as expected.
[
{
"v" : 2,
"key" : {
"_id" : 1
},
"name" : "_id_",
"ns" : "expireDocument.docs"
},
// second object-->
{
"v" : 2,
"key" : {
"expireAt" : 1
},
"name" : "expireAt_1",
"ns" : "expireDocument.docs",
"expireAfterSeconds" : 120,
"background" : true
}
]
- run
db.docs.drop()to drop the collection - Unpause the debugger.
- Again, after the script creates another
Doc, the debugger will pause online 22. While it's paused rundb.docs.getIndexes()again. For some reason, this time there won't be any second object that indicates there is expireAt information.
[
{
"v" : 2,
"key" : {
"_id" : 1
},
"name" : "_id_",
"ns" : "expireDocument.docs"
}
]
Why?
Why am I not getting consistent expirations set?
server.js Code
const mongoose = require('mongoose');
const docSchema = new mongoose.Schema({
createdAt: { type: Date, default: Date.now },
expireAt: { type: Date, default: Date.now, index: { expires: '2m' } },
});
const Doc = mongoose.model('Doc', docSchema);
const run = async function () {
// make document
const doc1 = await Doc.create({});
debugger;
// While paused:
// 1. run db.docs.getIndexes() in mongo shell and there will be a second object with "key":{ "expireAt":1}
// 2. then run db.docs.drop() to drop the documents
// 3. unpause script
// make 2nd document
const doc2 = await Doc.create({});
debugger; // run db.docs.getIndexes() in mongo shell and if you dropped in step #2 when script was pause at line 14, there will be no second object with "key":{ "expireAt":1}
};
mongoose
.connect('mongodb://localhost/expireDocument', {
useNewUrlParser: true,
useUnifiedTopology: true,
useFindAndModify: true,
})
.then(() => console.log('Successfully connect to MongoDB.\n'))
.catch((err) => console.error('Connection error', err));
run();