Подтвердить что ты не робот

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

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

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

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

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

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

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

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

4b9b3361

Ответ 1

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

Ответ 2

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

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

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

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

Ответ 3

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

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

Ответ 4

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

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

Например $addToSet:

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

$addToSet, когда он используется во встроенных документах в массиве, обсуждается/иллюстрируется здесь: fooobar.com/info/400515/...

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

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

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

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

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

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

Mongo увидит это как дубликат и НЕ этот объект для массива.