Я рассматриваю возможность использования MongoDB для хранения документов, содержащих список пар ключ / значение. Безопасный, но уродливый и раздутый способ хранения
[ ['k1' : 'v1'] , ['k2' : 'v2'], ...]
Но элементы документа по своей сути упорядочены в базовой структуре данных BSON, поэтому в принципе:
{k1 : 'v1', k2 : 'v2', ...}
должно быть достаточно. Однако я ожидаю, что большинство языковых привязок будет интерпретировать их как ассоциативные массивы и, следовательно, потенциально скремблировать порядок. Поэтому мне нужно знать:
Меня больше интересуют Javascript и PHP, но я также хотел бы узнать о других языках. Любая помощь приветствуется, или просто ссылка на некоторую документацию, где я могу перейти на RTM.
Начиная с версии 2.6, MongoDB сохраняет порядок полей, где это возможно. Тем не менее, поле _id
всегда на первом месте, поля переименования могут привести к переупорядочению. Однако я обычно старался не полагаться на такие детали. Как упоминается в первоначальном вопросе, есть еще и дополнительные слои, которые должны обеспечить какую-то гарантию стабильности заказа …
Оригинальный ответ:
Нет, MongoDB не дает гарантий относительно порядка полей :
«Нет гарантии, что заказ на поставку будет согласованным, или же после обновления».
В частности, обновления на месте, изменяющие размер документа, обычно меняют порядок полей. Например, если вы $set
поле, старое значение которого имело номер типа, а новое значение – NumberLong
, поля обычно NumberLong
.
Однако массивы сохраняют порядок правильно:
[ {'key1' : 'value1'}, {'key2' : 'value2'}, ... ]
Я не понимаю, почему это «уродливое» и «раздутое» вообще. Хранение списка сложных объектов не могло быть проще. Однако злоупотребление объектами в виде списков определенно уродливо: объекты имеют ассоциативную семантику массива (т. Е. Может быть только одно поле заданного имени), тогда как в списках / массивах нет:
// 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" } ] }
Имейте в виду, что MongoDB является объектной базой данных, а не хранилищем ключей / значений.
Начиная с Mongo 2.6.1, он хранит порядок ваших полей:
MongoDB сохраняет порядок полей документа после операций записи, за исключением следующих случаев:
- Поле _id всегда является первым полем в документе.
- Обновления, которые включают переименование имен полей, могут привести к переупорядочению полей в документе.
http://docs.mongodb.org/manual/release-notes/2.6/#insert-and-update-improvements
Одной из причин боли является сравнение документов друг с другом в оболочке.
Я создал проект, который создает пользовательский файл mongorc.js, который по умолчанию сортирует ключи документа, когда они распечатываются, поэтому, по крайней мере, вы можете видеть, что происходит в оболочке. Это называется Mongo Hacker, если вы хотите дать ему вихрь.
Хотя верно, что с Mongo 2.6.1 он сохраняет порядок, все равно нужно быть осторожным с операциями обновления.
mattwad утверждает, что обновления могут изменять порядок вещей, но есть, по крайней мере, еще одна проблема, о которой я могу думать.
Например $ addToSet:
https://docs.mongodb.com/manual/reference/operator/update/addToSet/
$ addToSet при использовании на встроенных документах в массиве обсуждается / приводится здесь: https://stackoverflow.com/a/21578556/3643190
В сообщении mnemosyn объясняет, как $ addToSet игнорирует порядок при сопоставлении элементов в его глубоком значении путем сравнения значений.
($ addToSet только добавляет записи, когда они уникальны)
Это актуально, если вы решили структурировать данные следующим образом:
[{key1: v1, key2: v2}, {key1: v3, key2: v4}]
С таким обновлением (обратите внимание на другой порядок в встроенном документе):
db.collection.update({_id: "id"},{$addToSet: {field: {key2: v2, key1: v1} }});
Mongo увидит это как дубликат и НЕ этот объект для массива.