MongoDB query for document older than 30 seconds
Asked Answered
E

4

8

Does anyone have a good approach for a query against a collection for documents that are older than 30 seconds. I'm creating a cleanup worker that marks items as failed after they have been in a specific state for more than 30 seconds.

Not that it matters, but I'm using mongojs for this one.

Every document has a created time associated with it.

Exceeding answered 5/2, 2014 at 23:47 Comment(0)
G
10

We are assuming you have a created_at or similar field in your document that has the time it was inserted or otherwise modified depending on which is important to you.

Rather than iterate over the results you might want to look at the multi option in update to apply your change to all documents that match your query. Setting the time you want to look past should be fairly straightforward

In shell syntax, which should be pretty much the same of the driver:

db.collection.update({
     created_at: {$lt: time },
     state: oldstate 
},
{$set: { state: newstate } }, false, true )

The first false being for upserts which does not make any sense in this usage and the second true marking for multi document update.

If the documents are indeed going to be short lived and you have no other need for them afterwards, then you might consider capped collections. You can have a total size or time to live option for these and the natural insertion order favours processing of queued entries.

Gear answered 6/2, 2014 at 0:26 Comment(0)
C
24

If you want to do this using mongo shell:

db.requests.find({created: {$lt: new Date((new Date())-1000*60*60*72)}}).count()

...will find the documents that are older than 72 hours ("now" minus "72*60*60*1000" msecs). 30 seconds would be 1000*30.

Constable answered 19/3, 2014 at 19:0 Comment(0)
G
10

We are assuming you have a created_at or similar field in your document that has the time it was inserted or otherwise modified depending on which is important to you.

Rather than iterate over the results you might want to look at the multi option in update to apply your change to all documents that match your query. Setting the time you want to look past should be fairly straightforward

In shell syntax, which should be pretty much the same of the driver:

db.collection.update({
     created_at: {$lt: time },
     state: oldstate 
},
{$set: { state: newstate } }, false, true )

The first false being for upserts which does not make any sense in this usage and the second true marking for multi document update.

If the documents are indeed going to be short lived and you have no other need for them afterwards, then you might consider capped collections. You can have a total size or time to live option for these and the natural insertion order favours processing of queued entries.

Gear answered 6/2, 2014 at 0:26 Comment(0)
J
4

You could use something like that:

var d = new Date();
d.setSeconds(d.getSeconds() - 30);

db.mycollection.find({ created_at: { $lt: d } }).forEach(function(err, doc) {} );
Jibber answered 6/2, 2014 at 0:2 Comment(1)
I wasn't sure how to get a date object in the right format to use with the query. This worked great. Thanks!Lacreshalacrimal
R
2

The TTL option is also an elegant solution. It's an index that deletes documents automatically after x seconds, see here: https://docs.mongodb.org/manual/core/index-ttl/

Example code would be:

db.yourCollection.createIndex({ created:1 }, { expireAfterSeconds: 30 } )

Remind answered 27/4, 2016 at 15:58 Comment(1)
For those who will be using TTL indexes, please take note: The TTL index does not guarantee that expired data will be deleted immediately upon expiration. There may be a delay between the time a document expires and the time that MongoDB removes the document from the database.Immunogenetics

© 2022 - 2024 — McMap. All rights reserved.