0

I've noticed that if we insert an object {a: 1, b: 2, c: 3}, in database it'll be stored as {c: 3, b:2, a: 1}. Why is MongooseJS doing this?

Is it for Performance Gain (or) some other logic?

Could anyone please explain this to me in detail?

2 Answers2

1

There is no such thing as properties order in object. If the order is important for you use an array.

The for...in statement iterates over the enumerable properties of an object, in original insertion order. For each distinct property [...]

However this seems to be implementation (browser) dependant.
In objects you can't rely on order of the properties as even various iteration methods may give various results.

strah
  • 6,557
  • 4
  • 30
  • 45
  • Yes, I do understand that properties order should not be considered in object. But If you're using a for..in loop, properties with numerical key[0-9] are sorted and handled before the alphanumeric keys [a-zA-Z0-9_.........] – ARAVIND KUMAR.S Jun 16 '17 at 11:27
  • If we're going to calculate the checksum of that object before and after insertion will produce different results – ARAVIND KUMAR.S Jun 16 '17 at 11:29
  • And also my question is about the logic behind the properties order reversal. which MongooseJS have implemented. – ARAVIND KUMAR.S Jun 16 '17 at 11:31
  • @ARAVINDKUMAR.S objects don't have an order. Any observed reversal of properties, or a particular order shown when iterating the object, should be considered to be purely coincidental and random, and cannot be relied upon. – robertklep Jun 16 '17 at 11:32
  • For preserving the order, we need to set retainKeyOrder property to true in the schema options. – ARAVIND KUMAR.S Jun 16 '17 at 11:33
  • @robertklep, why do they've provided for retainKeyOrder property. – ARAVIND KUMAR.S Jun 16 '17 at 11:37
0

Ordering of properties in objects is complex, as this answer explains: https://stackoverflow.com/a/38218582/893780

Even though it's not specified in the standard, normal property keys are stored in insertion order.

Internally, Mongoose uses a faster code path when cloning objects, that reverses the property order. It basically does this:

let oldObject = { a: 1, b: 2, c: 3 };
let newObject = {};

let keys = Object.keys(oldObject);
let i    = keys.length;

while (i--) {
  let k   = keys[i];
  let val = oldObject[k];
  newObject[k] = val;
}

Because normal keys are stored in insertion order, newObject will be the reverse of oldObject:

{ c: 3, b: 2, a: 1 }

However, because this can cause issues in queries, Mongoose added an option retainKeyOrder to prevent this reversal.

However, according to the same answer that I linked to above, you still can't rely on any order being imposed when using Object.keys() or for..in.

robertklep
  • 174,329
  • 29
  • 336
  • 330