18

I have a document with a field _id has type ObjectId, and a field created_at has type Date.

_id is of course increasing, and the value of created_at is current_date should be increasing.

So my question is :

  1. Is there any chance that 2 documents, A and B, A._id > B._id, but A.created_at < B.created_at.
  2. How to keep created_at as precise as possible, so the order of created_at corresponds to _id.
SiddAjmera
  • 38,129
  • 5
  • 72
  • 110
Joey
  • 1,233
  • 3
  • 11
  • 18
  • The only "real" chance would be where either the `_id` was generated at a source where the current "time" was behind the server instance and the `"created_at`" property was sourced from [`$currentDate`](https://docs.mongodb.org/manual/reference/operator/update/currentDate/) on the server itself, rather than remotely. Also despite "best efforts" the `"created_at"` could in fact be "changed", whereas the `_id` field is "immutable" and **cannot** be changed. So an `ObjectId` in `_id` can never change from it's initial value, but any other property has no such distinction. – Neil Lunn Apr 06 '16 at 04:49
  • https://docs.mongodb.org/manual/reference/method/ObjectId/ In the above link you can see that mongodb uses timestamp to create its Id..So I think there can't be a scenario when this could occur, unless you change the system time where your server is running.. – Anirudh Modi Apr 06 '16 at 04:49
  • @AnirudhModi Well "technically" there can be cases just as mentioned. The other thing to consider is that the "time" in an `ObjectId` is **not** accurate to the millisecond, where as any BSON `Date` will be. So multiple `ObjectId` values can in fact represent the "same time" ( though still be independently monotonic ), where this is "less likely" in a field containing a full `Date` object, or a numeric version of a "more precise" time measurement. Depends on usage, and generally a reasonably broad topic. – Neil Lunn Apr 06 '16 at 04:53
  • @NeilLunn So you mean if I do `db.test.update({"_id": ObjectId()}, {"$currentDate": { "created_at": { "$type": 'date' }}}, {upsert: true})` then sort by `created_at` and sort by `_id` will have the same result? – Joey Apr 06 '16 at 05:49
  • Mostly. As long as your clocks on the "client" and "server" are in sync. I was generally covering cases where there "could" be a difference. – Neil Lunn Apr 06 '16 at 05:52
  • @NeilLunn Thanks, I'm using mongodb to store chat messages which require strict order both in server side and client side(android/ios), i use _id to sort those messages, but client side have to use created_at to sort their local messages, if this worked then you solved my problem. – Joey Apr 06 '16 at 06:03

2 Answers2

38

you can use order_by on documents collection like

in Rails

Product.order_by("created_at desc")

in Mongodb for example

db.products.find().sort({"created_at": 1}) --- 1 for asc and -1 for desc
Sukanta
  • 585
  • 3
  • 6
  • 3
    I use `_id` to sort documents, it's primary key and will be very fast. – Joey Apr 06 '16 at 07:47
  • @xcaptain you are aware that you can index any field or even multiple fields and they, too, will be very fast. – Hughzi Apr 06 '16 at 07:52
  • @xcaptain you can do by _id by 'created_at' with '_id' and _id by default indexed – Sukanta Apr 06 '16 at 07:55
  • 1
    @Sukanta Nope, the service side sorting is easy, sort by `_id` is enough for my situation. The hard part is that the client side use sqlite to store those documents server returns, sqlite doesn't recognize MongoId so my document must contain a time field and have the same order with `_id` – Joey Apr 06 '16 at 11:30
1

Mongoose creates timestamps with field name "createdAt" and "updatedAt"

db.products.find().sort({"createdAt": 1}) 
justusrk
  • 11
  • 1
  • This might create a very high latency with large amount of data, specially if this field is not indexed. – Book Of Zeus Jun 15 '21 at 05:09
  • 1
    Good catch. We should index this if necessary. Look here https://stackoverflow.com/questions/38963470/is-the-mongoose-timestamps-schema-option-indexed – justusrk Jun 16 '21 at 09:37