Возможно ли, чтобы один и тот же точный Mongo ObjectId был сгенерирован для документа в двух разных коллекциях? Я понимаю, что это определенно маловероятно, но возможно ли?
Не вдаваясь в подробности, я спрашиваю, что с помощью приложения, над которым я работаю, мы показываем общедоступные профили избранных должностных лиц, которых мы надеемся превратить в полноправных пользователей нашего сайта. У нас есть отдельные коллекции для пользователей и избранных должностных лиц, которые в настоящее время не являются участниками нашего сайта. Существуют различные другие документы, содержащие различные данные об избранных должностных лицах, которые сопоставляются с лицом, использующим их избранный официальный ObjectId.
После создания учетной записи мы по-прежнему выделяем данные, связанные с избранным должностным лицом, но теперь они также являются частью коллекции пользователей с соответствующим ObjectId пользователей, чтобы сопоставить их профиль с взаимодействиями с нашим приложением.
Мы начали преобразование нашего приложения с MySql в Mongo несколько месяцев назад, и пока мы находимся в процессе перехода, мы сохраняем устаревший идентификатор MySql для обоих этих типов данных, а также теперь мы начинаем хранить выбранный официальный Mongo ObjectId в пользователях. документ для сопоставления с избранными официальными данными.
Я размышлял о том, чтобы просто указать новый пользовательский ObjectId в качестве предыдущего избранного официального ObjectId, чтобы упростить задачу, но хотел убедиться, что невозможно столкнуться с каким-либо существующим пользовательским ObjectId.
Спасибо за понимание.
Изменить: вскоре после публикации этого вопроса я понял, что предложенное мной решение не было очень хорошей идеей. Было бы лучше просто сохранить текущую схему, которая у нас есть, и просто привязать к избранному должностному лицу '_id' в пользовательском документе.
Ответы:
Короткий ответ
Просто чтобы добавить прямой ответ на ваш первоначальный вопрос: ДА, если вы используете генерацию идентификатора объекта BSON, то для большинства драйверов идентификаторы почти наверняка будут уникальными для разных коллекций. См. Ниже, что означает «почти наверняка».
Длинный ответ
Идентификаторы объекта BSON, сгенерированные драйверами Mongo DB, с большой вероятностью будут уникальными для разных коллекций. Это в основном из-за последних 3 байтов идентификатора, который для большинства драйверов генерируется с помощью статического счетчика приращения. Этот счетчик не зависит от коллекции; это глобально. Например, драйвер Java использует случайно инициализированный статический элемент AtomicInteger.
Так почему же в документах Mongo говорится, что идентификаторы «весьма вероятно» будут уникальными, вместо того, чтобы прямо сказать, что они БУДУТ уникальными? Возможны три варианта, при которых вы не получите уникальный идентификатор (сообщите мне, если есть другие):
Перед этим обсуждением напомним, что идентификатор объекта BSON состоит из:
[4 байта секунды с начала эпохи, 3 байта машинного хэша, 2 байта идентификатора процесса, 3 байта счетчика]
Вот три возможности, поэтому вы судите сами, насколько велика вероятность получить обман:
1) Переполнение счетчика: в счетчике 3 байта. Если вам случится вставить более 16 777 216 (2 ^ 24) документов за одну секунду на том же компьютере, в одном процессе, вы можете переполнить увеличивающиеся байты счетчика и получить два идентификатора объекта, которые имеют одно и то же время, машина , значения процесса и счетчика.
2) Счетчик без приращения: некоторые драйверы Mongo используют случайные числа вместо увеличения числа для байтов счетчика. В этих случаях существует вероятность 1/16 777 216 сгенерировать неуникальный идентификатор, но только если эти два идентификатора сгенерированы в одну и ту же секунду (то есть до того, как временной раздел идентификатора обновится до следующей секунды), в одну и ту же секунду. машина, в том же процессе.
3) Обработка и обработка хэша с одинаковыми значениями. Значения идентификатора компьютера и идентификатора процесса могут, в весьма маловероятном сценарии, соответствовать одним и тем же значениям для двух разных компьютеров. Если это произойдет, и в то же время два счетчика на двух разных машинах в течение одной и той же секунды сгенерируют одно и то же значение, то вы получите повторяющийся идентификатор.
Это три сценария, на которые следует обратить внимание. Сценарии 1 и 3 кажутся крайне маловероятными, а сценария 2 можно полностью избежать, если вы используете правильный драйвер. Вам нужно будет проверить источник драйвера, чтобы знать наверняка.
источник
ObjectId
что и раньше, пока машинный хэш, идентификатор процесса и счетчик будут одинаковымиObjectIds генерируются на стороне клиента аналогично UUID, но с некоторыми более приятными свойствами для хранения в базе данных, такими как приблизительное увеличение порядка и бесплатное кодирование времени их создания. Ключевым моментом для вашего варианта использования является то, что они разработаны, чтобы гарантировать уникальность с высокой вероятностью, даже если они созданы на разных машинах.
Теперь, если вы имели в виду поле _id в целом, мы не требуем уникальности для всех коллекций, поэтому можно безопасно повторно использовать старый _id. В качестве конкретного примера, если у вас есть две коллекции,
colors
иfruits
, обе могут одновременно иметь объект вроде{_id: 'orange'}
.Если вы хотите узнать больше о том, как создаются ObjectIds, вот спецификация: http://www.mongodb.org/display/DOCS/Object+IDs#ObjectIDs-BSONObjectIDSpecification
источник
Если у кого-то возникают проблемы с дублированием идентификаторов Mongo ObjectID, вы должны знать, что, несмотря на маловероятность дублирования, происходящего в самом Mongo, в Mongo возможно создание дубликатов _id с помощью PHP.
Сценарий использования, когда это происходило с регулярностью для меня, - это когда я просматриваю набор данных и пытаюсь ввести данные в коллекцию.
Массив, содержащий данные для инъекций, должен быть явно сброшен на каждой итерации, даже если вы не указываете значение _id. По какой-то причине процесс INSERT добавляет Mongo _id в массив, как если бы это была глобальная переменная (даже если массив не имеет глобальной области видимости). Это может повлиять на вас, даже если вы вызываете вставку в отдельном вызове функции, где вы обычно ожидаете, что значения массива не сохранятся обратно в вызывающую функцию.
Для этого есть три решения:
unset()
поле _id из массиваarray()
каждый раз, когда вы просматриваете свой набор данныхЯ предполагаю, что это ошибка в интерфейсе PHP, а не проблема с Mongo, но если вы столкнетесь с этой проблемой, просто отключите _id, и все будет в порядке.
источник
Нет никаких гарантий относительно уникальности ObjectId для разных коллекций. Даже если это очень маловероятно, это был бы очень плохой дизайн приложения, который полагался бы на уникальность _id в коллекциях.
Это легко проверить в оболочке mongo:
MongoDB shell version: 1.6.5 connecting to: test > db.foo.insert({_id: 'abc'}) > db.bar.insert({_id: 'abc'}) > db.foo.find({_id: 'abc'}) { "_id" : "abc" } > db.bar.find({_id: 'abc'}) { "_id" : "abc" } > db.foo.insert({_id: 'abc', data:'xyz'}) E11000 duplicate key error index: test.foo.$_id_ dup key: { : "abc" }
Итак, абсолютно не полагайтесь на то, что _id уникален для разных коллекций, и, поскольку вы не контролируете функцию генерации ObjectId, не полагайтесь на нее.
Можно создать что-то похожее на uuid, и если вы сделаете это вручную, у вас может быть лучшая гарантия уникальности.
Помните, что вы можете помещать объекты разных «типов» в одну и ту же коллекцию, так почему бы просто не поместить ваши две «таблицы» в одну и ту же коллекцию. Они будут использовать одно и то же пространство _id и, следовательно, будут гарантированно уникальны. Переход от «предполагаемого» к «зарегистрированному» был бы простым переключением поля ...
источник