The problem
I have a MongoDB collection of Session documents with three fields: a user, a fromTimestamp and a toTimestamp. In my code, I have a list of users whose toTimestamps I need to update to now.
For every user on my list:
- If there is an existing
Sessionwith thetoTimestampbeing no further than 1 minute ago, I want it updated to now. - If there isn't one, I want to create a new
Session, with bothfromTimestampsandtoTimestampbeing set to now.
Can I achieve this with one or two queries, in an efficient way?
Current solution
What I am currently doing, is using findMany to find all matching existing Sessions, getting their ID's and users. Then a bulk write with updateMany updates all the sessions with the collected ID's. A list of users gets created that were not returned from the initial query - these are the users that didn't have matching Sessions. For these, another bulk write inserts new Sessions.
However, this is 3 queries, and requires looping through all users to find which ones didn't have a matching Session. There might be thousands of users and I'm looking for a solution that will solve this efficiently, hopefully with a single query, without needing to compute differences in local code.
Sample data
Suppose the database contains these values:
Session(user: Alice, fromTimestamp: 0, toTimestamp: 10)
Session(user: Bob, fromTimestamp: 5, toTimestamp: 15)
Session(user: Claire: fromTimestamp: 0, toTimestamp: 20)
The timestamp now is 25.
We get an update list of: Alice, Claire, Dan. Looking for sessions up to 10 ago, concerning these users, we find just Claire. Dan doesn't have a session already, Alice does, but it's toTimestamp is more than 10 ago. So there is only one session to update: Claire. It's toTimestamp is set to now, which is 25. That leaves Alice and Dan, for which we create new sessions. The resulting database is:
Session(user: Alice, fromTimestamp: 0, toTimestamp: 10)
Session(user: Bob, fromTimestamp: 5, toTimestamp: 15)
Session(user: Claire: fromTimestamp: 0, toTimestamp: 25)
Session(user: Alice: fromTimestamp: 25, toTimestamp: 25)
Session(user: Dan: fromTimestamp: 25, toTimestamp: 25)
For users with recent sessions, the sessions are extended. For users with no recent sessions, new sessions are created.