Может ли MongoDB и его драйверы сохранять порядок элементов документа - PullRequest
13 голосов
/ 20 декабря 2011

Я рассматриваю возможность использования MongoDB для хранения документов, которые содержат список пар ключ / значение.Безопасный, но безобразный и раздутый способ сохранить это как

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

Но элементы документа изначально упорядочены в базовой структуре данных BSON, поэтому в принципе:

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

должно быть достаточно,Однако я ожидаю, что большинство языковых привязок будет интерпретировать их как ассоциативные массивы и, таким образом, потенциально зашифровывать порядок.Так что мне нужно знать:

  • Сам ли MongoDB обещает сохранить порядок элементов второй формы.
  • У языковых привязок есть некоторый API, который может извлекать его упорядоченную форму - даже если обычный «удобный» API возвращает ассоциативный массив.

Меня больше всего интересуют Javascript и PHPздесь, но я также хотел бы знать о других языках.Любая помощь приветствуется, или просто ссылка на документацию, где я могу перейти на RTM.

Ответы [ 4 ]

12 голосов
/ 20 декабря 2011

Начиная с версии 2.6, MongoDB сохраняет порядок полей, где это возможно. Однако, поле _id всегда стоит первым, а переименование полей может привести к переупорядочению.Однако я обычно стараюсь не полагаться на подобные детали.Как упоминается в первоначальном вопросе, существуют также дополнительные уровни, которые необходимо учитывать, и каждый из них должен предоставить какую-то гарантию стабильности порядка ...

Оригинальный ответ:

Нет, MongoDB не дает гарантий относительно порядка полей :

"Нет никаких гарантий, что порядок полей будет постоянным или таким же после обновления."

В частности, обновления на месте, которые изменяют размер документа, обычно изменяют порядок полей.Например, если вы $set поле, старое значение которого было типового номера, а новое значение - 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 - это объектная база данных, а не хранилище ключей / значений.

8 голосов
/ 14 мая 2014

Начиная с Mongo 2.6.1, он сохраняет порядок ваших полей:

MongoDB сохраняет порядок полей документа после операций записи, за исключением следующих случаев:

  • Поле _id всегда является первым полем в документе.
  • Обновления, которые включают переименование имен полей, могут привести к переупорядочению полей в документе.

** 1014

0 голосов
/ 30 января 2017

Хотя верно, что в 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}
}});

Монго увидит это как дубликат, а НЕ этот объект в массиве.

0 голосов
/ 14 марта 2014

Одной из основных проблем этого является сравнение документов друг с другом в оболочке.

Я создал проект, который создает пользовательский файл mongorc.js, который сортирует ключи документов по умолчанию для вас, когда онираспечатаны, так что, по крайней мере, вы можете ясно видеть, что происходит в оболочке.Он называется Mongo Hacker , если вы хотите, чтобы это произошло.

...