0

With a compound index like the following

db.data.ensureIndex({ userId: 1, myObject: 1 })

Will the following find use this index?

db.data.find({ 
  userId: 1,
  myObject: {
    a:'test',
    b:'test2'
  }
})

I know in Javascript that objects don't preserve their order so is this the same in Mongo?

So what will happen if I have documents with objects in different orders like this.

{
  _id: ObjectId,
  userId:1,
  myObject: {
    b: 'test',
    a: 'test2'
  }
},

{
  _id: ObjectId,
  userId:1,
  myObject: {
    b: 'test',
    a: 'test2'
  }
},

{
  _id: ObjectId,
  userId:2,
  myObject: {
    b: 'test',
    a: 'test2'
  }
}

Does the order of the properties matter when indexing an object like above?

EDIT: In the documentation, http://docs.mongodb.org/manual/core/index-single/ it says "When performing equality matches on subdocuments, field order matters and the subdocuments must match exactly."

And in their example, the following would work

db.factories.find( { metro: { city: "New York", state: "NY" } } )

but if the metro fields were the other way around it wont work

db.factories.find( { metro: { state: "NY", city: "New York" } } )

So how do you preserve the property order in Javascript/Node when the language itself doesn't support it?

Neil Lunn
  • 130,590
  • 33
  • 275
  • 280
Tim Fairbrother
  • 898
  • 2
  • 8
  • 20

2 Answers2

1

Actually, JavasScript or JSON notation objects do preserve their order. While some top level properties might shuffle around if MongoDB has to move them as a document grows, generally speaking this "sub-level" document should not change from the order in which it was originally inserted.

That said some languages try to order their "Hash", "Map", "Dict" keys by default, and therefore it becomes important to find and "ordered" or "indexed" form when dealing with these, but that is another issue.

To your question of an "index" for MongoDB affecting this order, no it does not. In fact the index you have added, though it does not error as such, does not really have any value as an Object or {} essentially does not have a value for an index to act on.

What you can do is this:

db.data.ensureIndex({ "userId": 1, "myObject.a": 1 })

Which keeps an ascending index on the "a" property of your object. That is useful if this is regularly viewed in queries.

You can also have problems with positions if you attempt to query like this:

db.data.find({ "Object": { a: "test2", b: "test" } })

Where the actual stored keys are not in order. But this is typically fixed by the "dot notation" form:

db.data.find({ "Object.a": "test2", "Object.b": "test" })

Which will not care about the actual order of keys.

But the index you defined does not keep the "keys" in insertion order, that is entirely language specific

Neil Lunn
  • 130,590
  • 33
  • 275
  • 280
1

The order matters for indexes on sub-documents. To quote the documentation:

This query returns the above document. When performing equality matches on subdocuments, field order matters and the subdocuments must match exactly. For example, the following query does not match the above document

Consider this document:

{
  _id: ObjectId(...),
  metro: {
           city: "New York",
           state: "NY"
         },
  name: "Giant Factory"
}

and this index:

db.factories.ensureIndex( { metro: 1 } )

this query matches:

db.factories.find( { metro: { city: "New York", state: "NY" } } )

and this one does not:

db.factories.find( { metro: { state: "NY", city: "New York" } } )

See http://docs.mongodb.org/manual/core/index-single/#indexes-on-subdocuments and http://docs.mongodb.org/manual/reference/method/db.collection.find/#query-subdocuments

John Petrone
  • 24,904
  • 5
  • 57
  • 67
  • Thanks, I found that in the docs just after I posted this question. I'm not sure this has sunk in yet for me though. In Chrome or node, objects dont maintain their order http://stackoverflow.com/questions/5525795/does-javascript-guarantee-object-property-order – Tim Fairbrother Jun 04 '14 at 05:45
  • Honestly I'd avoid doing things that are order dependent. In this case, index the individual fields of the sub-document, not the sub-document itself. – John Petrone Jun 04 '14 at 05:47
  • What I wanted to do was have a unique index on userId and another field that is a subdocument that can contain many different combinations of fields (like address). Is it possible to do without listing each one in the index creation? – Tim Fairbrother Jun 04 '14 at 06:03
  • you will generally need to index each subdocument field separately. – John Petrone Jun 11 '14 at 01:30