13

I am considering using MongoDB to store documents that include a list of key/value pairs. The safe but ugly and bloated way to store this is as

[ ['k1' : 'v1'] , ['k2' : 'v2'],  ...]

But document elements are inherently ordered within the underlying BSON data structure, so in principle:

{k1 : 'v1', 
 k2 : 'v2',  ...}

should be enough. However I expect most language bindings will interpret these as associative arrays, and thus potentially scramble the ordering. So what I need to know is:

  • Does MongoDB itself promise to preserve item ordering of the second form.
  • Do language bindings have some API which can extract it ordered form -- even if the usual "convenient" API returns an associative array.

I am mostly interested in Javascript and PHP here, but I would also like to know about other languages. Any help is appreciated, or just a link to some documentation where I can go RTM.

Funk Forty Niner
  • 74,450
  • 15
  • 68
  • 141
Adrian Ratnapala
  • 5,485
  • 2
  • 29
  • 39
  • 1
    the mongodb user forum is the best place to ask these Qs; the mongodb developers are very helpful in answering questions like this and would be able to give you authoritative answers. https://groups.google.com/forum/#!forum/mongodb-user – Jason S Dec 20 '11 at 14:20
  • 1
    @JasonS thanks for that. One reason I asked here is that the problem involves so many different languages/standards that I didn't know where to look. But you are right, Mongo sits in the centre of them all. – Adrian Ratnapala Dec 20 '11 at 14:32
  • 1
    This is actually the more appropriate place to ask. – Remon van Vliet Dec 20 '11 at 15:11
  • 2
    Well this is where got the answer. – Adrian Ratnapala Dec 21 '11 at 15:39

4 Answers4

12

From Version 2.6 on, MongoDB preserves the order of fields where possible. However, the _id field always comes first an renaming fields can lead to re-ordering. However, I'd generally try not to rely on details like this. As the original question mentions, there are also additional layers to consider which each must provide some sort of guarantee for the stability of the order...

Original Answer:

No, MongoDB does not make guarantees about the ordering of fields:

"There is no guarantee that the field order will be consistent, or the same, after an update."

In particular, in-place updates that change the document size will usually change the ordering of fields. For example, if you $set a field whose old value was of type number and the new value is NumberLong, fields usually get re-ordered.

However, arrays preserve ordering correctly:

[ {'key1' : 'value1'}, {'key2' : 'value2'}, ... ]

I don't see why this is "ugly" and "bloated" at all. Storing a list of complex objects couldn't be easier. However, abusing objects as lists is definitely ugly: Objects have associative array semantics (i.e. there can only be one field of a given name), while lists/arrays don't:

// not ok:
db.foo2.insert({"foo" : "bar", "foo" : "lala" });
db.foo2.find();
{ "_id" : ObjectId("4ef09cd9b37bc3cdb0e7fb26"), "foo" : "lala" }

// a list can do that
db.foo2.insert({ 'array' : [ {'foo' : 'bar'}, { 'foo' : 'lala' } ]});
db.foo2.find();
{ "_id" : ObjectId("4ef09e01b37bc3cdb0e7fb27"), "array" : 
      [ { "foo" : "bar" }, { "foo" : "lala" } ] }

Keep in mind that MongoDB is an object database, not a key/value store.

mnemosyn
  • 45,391
  • 6
  • 76
  • 82
  • 1
    Clean... nothing more to add.. +1 – RameshVel Dec 20 '11 at 15:52
  • 2
    Fine, I will do it that way. I still say it is ugly, but it is quite reasonable that MongoDB works that way. "Objects have associative array semantics" is a javascript-ism (normally I wouldn't use the word object for such data structures). From my (superficial) readings about MongoDB, I thought it was a database of BSON documents -- and BSON has a very clear specification, in which elements are ordered. Instead MongoDB is a store of Javascript-like objects (or python-like dictionaries) which happens to use BSON under the hood. Fair enough. – Adrian Ratnapala Dec 21 '11 at 15:45
  • "MongoDB does not make guarantees about the ordering of fields" is wrong. MongoDB does make certain strict guarantees about the order of fields. It doesn't guarantee it after every operation (such as "*after an update*"), but it definitely makes guarantees. That said, depending on dictionaries preserving order is a nightmare and almost always best avoided, since most languages' native dictionaries don't. – Glenn Maynard Feb 09 '14 at 15:50
  • I can see that this one sentence is not perfectly correct because every deterministic system makes guarantees, if you will. But I find it hardly warrants a downvote. Care to elaborate what these guarantees are, exactly, where they are documented (except for the source code, but we don't want to rely on implementation details) and how they can be used in a practical environment where a single point of code has little chance of knowing which operations were performed on the data? – mnemosyn Feb 10 '14 at 08:56
  • @mnemosyn I think the documentation does make a guarntee, but in a very indirect way that doesn't inspire much confidence. They say MongoDB stores BSON documents, an in BSON list of kv-pairs are ordered (since they are *lists*). But that is useless if the language bindings don't expose the lists in a guaranteed way. – Adrian Ratnapala Mar 11 '14 at 12:41
  • 1
    This answer seems to be outdated as of 2017 – noahlz Sep 06 '17 at 11:58
9

As of Mongo 2.6.1, it DOES keep the order of your fields:

MongoDB preserves the order of the document fields following write operations except for the following cases:

  • The _id field is always the first field in the document.
  • Updates that include renaming of field names may result in the reordering of fields in the document.

http://docs.mongodb.org/manual/release-notes/2.6/#insert-and-update-improvements

Community
  • 1
  • 1
mattwad
  • 1,743
  • 17
  • 13
0

One of the pain points of this is comparing documents to one another in the shell.

I've created a project that creates a custom mongorc.js which sorts the document keys by default for you when they are printed out so at least you can see what is going on clearly in the shell. It's called Mongo Hacker if you want to give it a whirl.

Tyler Brock
  • 29,626
  • 15
  • 79
  • 79
0

Though it's true that, as of Mongo 2.6.1, it does preserve order, one should still be careful with update operations.

mattwad makes the point that updates can reorder things, but there's at least one other concern I can think of.

For example $addToSet:

https://docs.mongodb.com/manual/reference/operator/update/addToSet/

$addToSet when used on embedded documents in an array is discussed / exemplified here: https://stackoverflow.com/a/21578556/3643190

In the post, mnemosyn explains how $addToSet disregards the order when matching elements in its deep value by value comparison.

($addToSet only adds records when they're unique)

This is relevant if one decided to structure data like this:

[{key1: v1, key2: v2}, {key1: v3, key2: v4}]

With an update like this (notice the different order on the embedded doc):

db.collection.update({_id: "id"},{$addToSet: {field:
{key2: v2, key1: v1}
}});

Mongo will see this as a duplicate and NOT this object to the array.

Community
  • 1
  • 1
jmbartho
  • 48
  • 5