Reputation: 10242
Yeah the title may sound silly but I have two collections: Visitors and Chats. Chat has a visitor while visitor has many chats. Periodically I delete visitors that have a last_activity
field lower that x days but I wouldn't wanna delete a visitor who has chat(s) so I need a way to delete from visitors where last_activity < days_unix_milliseconds and _id not in(select visitor_id from chats)
I have a working code for the first part (last activity), need help with the 2nd:
Visitors.remove({
last_update: {
$lt: (new Date()).getTime() - 3600000 * 24 * 7
}
}, function(error){
});
Upvotes: 0
Views: 104
Reputation: 3760
So each chat has a field visitor_id
and you want to delete only visitors whose _id
does not appear as a visitor_id
in a chat? You would have to loop over all visitors, check last_activity
for each, and if it is a candidate for deletion, do a find()
on chats with that visitor's _id
. If it turns up no documents, you can delete that visitor.
When you iterate over all visitors, you do that with a MongoDB cursor (the result of a find()
). The cursor is implemented in such a way that you can safely delete documents from the underlying collection while iterating over it.
The trick is that you don't attempt to express everything in a single remove()
call. You iterate, check, and delete as part of the iteration. You want to make sure that the find()
inside the loop is very fast, by adding an index on visitor_id
to the chats collection.
Upvotes: 2
Reputation: 36774
My advice would be to change your schema so that you can do this with just one query. In this case, I would probably just keep a field with each visitor
that tells you how many chats it has. You can simple increase this each time a user starts a chat with:
db.visitors.update( { visitor_id: XXX }, { $inc: { 'chat_count': 1 } } );
And when it ends:
db.visitors.update( { visitor_id: XXX }, { $inc: { 'chat_count': -1 } } );
And then removing all visitors that don't have a chat is as simple as:
db.visitors.remove( { last_activity: { $lt: XXX }, chat_count: { $lt: 1 } } );
Upvotes: 6