3

I have a query that is generated in my Node backend - if I log it out and run it in Mongo shell then all is fine, however, if I use mongoose to do Model.find(query), then some strange property re-ordering takes place and the query breaks.

The query in question is:

{
    "attributes": {
        "$all": [
            {
                "attribute": "an id",
                "value": "a value",
                "deletedOn": null
            },
            {
                "attribute": "an id again",
                "value": "a value",
                "deletedOn": null
            }
        ]
    }
}

However, the output from mongoose debug is:

users.find({ 
    attributes: { 
        '$all': [ 
            { 
                deletedOn: null,
                attribute: 'an id',
                value: 'a value'
            },
            {
                deletedOn: null,
                attribute: 'an id again',
                value: 'a value'
            }
        ]
    } 
},
    { fields: {} }
)

The only change is the shifting of the deletedOn field from last position to first position in the object. This means the query returns no results.

Are there any solutions to this issue?

Alex Young
  • 3,828
  • 1
  • 14
  • 33
  • http://mongoosejs.com/docs/guide.html#retainKeyOrder (although I'm not sure if that will work on `$all`). – robertklep Aug 07 '17 at 14:26
  • "The retainKeyOrder option was removed, mongoose will now always retain the same key position when cloning objects. If you have queries or indexes that rely on reverse key order, you will have to change them." [mongoosejs migrating to 5.x - retain-key-order](https://mongoosejs.com/docs/migrating_to_5.html#retain-key-order) – Boris Apr 16 '19 at 15:32

2 Answers2

0

Object properties in JavaScript are not ordered. You cannot ensure the order of properties on a JavaScript object and different implementations may order them differently. See this answer on a related question for some other info.

The essential key is that from the spec (ECMAScript) we get: "An object is a member of the type Object. It is an unordered collection of properties each of which contains a primitive value, object, or function. A function stored in a property of an object is called a method."

There is no "solution", because this is expected behavior. So the real question is, why does the order matter to you? What are you trying to do?

Jordan Kasper
  • 12,144
  • 3
  • 33
  • 52
  • 1
    The order matters because when querying MongoDB { a: 1, b: 2 } is not equal to { b: 2. a: 1 } - mongo uses BSON instead of JSON where property order is consistent. – Alex Young Aug 07 '17 at 13:52
0

Adding on the previous answer, if order is important to you, you should use array instead of objects.

for example:

"$all": [
    [
        {"attribute": "an id"},
        {"value": "a value"},
        {"deletedOn": null},
    ],
    ...etc.
]
Coffee
  • 95
  • 1
  • 9