Mongoose expiration not setting- expiration not showing in getIndexes

Viewed 103

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:

  1. Download the small repo here. You can also see the server.js code below.
  2. Open the folder in VScode.
  3. CTR+` to open terminal. Run npm i
  4. Click the debugger icon. At the top left play Expire Document debugger.
  5. After the script creates a Doc the debugger pauses on line 15. While paused, open a new terminal.
  6. Run mongo and then use expireDocument to navigate to the correct database.
  7. 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
        }
]
  1. run db.docs.drop() to drop the collection
  2. Unpause the debugger.
  3. Again, after the script creates another Doc, the debugger will pause on line 22. While it's paused run db.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();
0 Answers
Related