[GODRIVER-2479] Add Before/After for primitive.ObjectId to include counter Created: 29/Jun/22  Updated: 24/Jan/24  Resolved: 02/Aug/22

Status: Closed
Project: Go Driver
Component/s: API
Affects Version/s: None
Fix Version/s: None

Type: New Feature Priority: Unknown
Reporter: Ed Pelc Assignee: Matt Dale
Resolution: Done Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified


 Description   

When working with mongodb documents where you do an insert of multiple documents at once and let mongodb create the `_id` field they can end up with the same timestamp. This makes it difficult in application code to compare ObjectId fields soley based on the timestamp.

 

I think we should add `Before(id)` and `After(id)` methods to `primitive.ObjectId` which takes both the timestamp and counter field into consideration when comparing ObjectId so that it matches the sort order comparisons done on the server.

 

Common existing code is `firstId.Timestamp().Before(secondID.Timestamp())` but this subtle breaks when doing find queries for many documents created at the same time and trying to iterator it without a capped collection. ie when you do something like `{_id:{$gt:lastIDSeen}}` it ends up not working due to these faulty ID comparisons.

 

These methods are also required because you cannot do greater than or less than comparisons on a byte array in go. Only the equality operator works.



 Comments   
Comment by Matt Dale [ 02/Aug/22 ]

epelc@greatcloak.com I'm glad that was helpful!

Keep in mind that ObjectIDs aren't guaranteed to strictly reflect insertion order, only generally reflect insertion order. For more information on ordering with ObjectIDs, check out this helpful reply on the MongoDB developer forum.

I'm closing this as resolved. Please feel free to reply here or open a new ticket if you have more questions.

Comment by Ed Pelc [ 28/Jul/22 ]

Thanks @Matt Dale this should work. Couldn't find any info on how the server sorted Object IDs but this answers it.

Comment by Matt Dale [ 25/Jul/22 ]

Hey epelc@greatcloak.com, thanks for the question! You can use bytes.Compare to do the same sort order comparison that the server does. For example:

o1 := primitive.NewObjectID()
o2 := primitive.NewObjectID()
 
if bytes.Compare(o1[:], o2[:]) < 0 {
	fmt.Printf("%v is less than %v\n", o1, o2)
}

Check out a working example here. Does that work for your use case?

Generated at Thu Feb 08 08:38:43 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.