Может ли MongoDB и его драйверы сохранить порядок элементов документа


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

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

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

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

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

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

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

Author: Funk Forty Niner, 2011-12-20

4 answers

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

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

Нет, MongoDB не делает гарантии в отношении упорядочения полей:

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

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

 11
Author: mnemosyn, 2017-09-06 20:21:25

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

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

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

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

 7
Author: mattwad, 2014-05-14 14:39:39

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

Я создал проект, который создает пользовательский mongorc.js который сортирует ключи документа по умолчанию для вас, когда они распечатаны, чтобы, по крайней мере, вы могли четко видеть, что происходит в оболочке. Он называется Монго Хакер, если вы хотите его раскрутить.

 0
Author: Tyler Brock, 2014-03-13 22:49:07

Хотя это правда, что, начиная с Mongo 2.6.1, он сохраняет порядок, все равно следует быть осторожным с операциями обновления.

Мэттвад подчеркивает, что обновления могут изменять порядок вещей, но есть, по крайней мере, еще одна проблема, о которой я могу подумать.

Например, $addToSet:

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

$addToSet при использовании во встроенных документах в массиве обсуждается/иллюстрируется здесь: https://stackoverflow.com/a/21578556/3643190

В этом посте мнемозин объясняет, как $addToSet игнорирует порядок при сопоставлении элементов в его глубоком значении путем сравнения значений.

($addToSet добавляет записи только в том случае, если они уникальны)

Это актуально, если кто-то решил структурировать данные следующим образом:

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

С таким обновлением (обратите внимание на другой порядок во встроенном документе):

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

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

 0
Author: jmbartho, 2017-05-23 10:31:25